CVR-opslag i Go

I Go klarer standardbiblioteket det hele: <code>net/http</code> til kaldet og <code>encoding/json</code> til at læse svaret ind i en struct. Ingen API-nøgle, ingen eksterne pakker.

Slå en virksomhed op på CVR-nummer

Structen indeholder kun de felter, du har brug for. Felter i svaret, som ikke er med i structen, bliver ignoreret.

go
package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"time"
)

type Owner struct {
	Name           string `json:"name"`
	Type           string `json:"type"`
	OwnershipRange string `json:"ownership_range"`
}

type Company struct {
	Vat          int     `json:"vat"`
	Name         string  `json:"name"`
	Address      string  `json:"address"`
	Zipcode      int     `json:"zipcode"`
	City         string  `json:"city"`
	IndustryDesc string  `json:"industrydesc"`
	Protected    bool    `json:"protected"`
	Ejere        []Owner `json:"ejere"`
}

var ErrNotFound = errors.New("cvr: company not found")

var client = &http.Client{Timeout: 15 * time.Second}

func GetCompany(cvr int) (*Company, error) {
	res, err := client.Get(fmt.Sprintf("https://apicvr.dk/api/v1/%d", cvr))
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	switch res.StatusCode {
	case http.StatusOK:
		var c Company
		return &c, json.NewDecoder(res.Body).Decode(&c)
	case http.StatusNotFound:
		return nil, ErrNotFound
	default:
		return nil, fmt.Errorf("cvr: unexpected status %d", res.StatusCode)
	}
}

func main() {
	c, err := GetCompany(24256790)
	if err != nil {
		panic(err)
	}
	fmt.Println(c.Name, c.Zipcode, c.City)
	for _, o := range c.Ejere {
		fmt.Println(o.Name, o.OwnershipRange)
	}
}

Søg på virksomhedsnavn

Fuzzy-søgningen finder virksomheder, selv om navnet er stavet lidt forkert. Hvert hit har name, cvr_number, industrycode og industrytext.

go
type Hit struct {
	Name         string `json:"name"`
	CvrNumber    int    `json:"cvr_number"`
	IndustryText string `json:"industrytext"`
}

func Search(name string) ([]Hit, error) {
	res, err := client.Get("https://apicvr.dk/api/v1/search/fuzzy/" + url.PathEscape(name))
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	var hits []Hit
	return hits, json.NewDecoder(res.Body).Decode(&hits)
}

// Kræver import af "net/url".

Håndter fejl

StatusBetydning
200Virksomheden blev fundet. Svaret er JSON.
404Der findes ingen virksomhed med det CVR-nummer. Body: {"detail": {"error": "NOT_FOUND"}}
422CVR-nummeret er ikke et tal.
502CVR-registret svarede ikke. Prøv igen om lidt.

I eksemplet bliver 404 til ErrNotFound, så du kan tjekke det med errors.Is(err, ErrNotFound). Andre statuskoder giver en almindelig fejl.

Tjek altid protected, før du bruger data til markedsføring. Er feltet true, har virksomheden frabedt sig reklamehenvendelser.

Ofte stillede spørgsmål

Hvorfor er nogle felter null?

Felter uden værdi i CVR er null i JSON. Med almindelige typer i structen får du nulværdien (fx en tom streng). Brug pointere som *string, hvis du skal kende forskel.

Kan jeg kalde API'et parallelt fra goroutines?

Ja, men hold tempoet nede, fx med en semaphore på få samtidige kald. Har du brug for vedvarende høj trafik, så skriv til [email protected].