A DOI (Digital Object Identifier) is a standard used to uniquely identify digital content such as scientific articles, datasets, and publications. In this article, we’ll see how to generate and manage a DOI in Go, simulating interaction with registration APIs (such as those from Crossref or DataCite).
1. What is a DOI
A DOI is an alphanumeric string, usually composed of a prefix and a suffix separated by a slash. For example: 10.1234/abcde.2025.001
. DOIs are generally registered through certified agencies that provide APIs for creation, updating, and resolution.
2. Generating a DOI
You can generate a DOI locally by creating a string that follows the correct syntax. Here’s a simple example in Go:
package main
import (
"crypto/rand"
"fmt"
)
func generateDOI(prefix string) string {
suffix := make([]byte, 6)
rand.Read(suffix)
for i := range suffix {
suffix[i] = "abcdefghijklmnopqrstuvwxyz0123456789"[suffix[i]%36]
}
return fmt.Sprintf("%s/%s", prefix, string(suffix))
}
func main() {
doi := generateDOI("10.1234")
fmt.Println("Generated DOI:", doi)
}
3. Registration via API
After generating a DOI, you need to register it with an organization like DataCite. Here’s an example HTTP POST request to register a DOI:
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
type Metadata struct {
Data struct {
Type string `json:"type"`
Attributes struct {
DOI string `json:"doi"`
Title string `json:"titles"`
// Other metadata
} `json:"attributes"`
} `json:"data"`
}
func registerDOI(doi, title string) error {
metadata := Metadata{}
metadata.Data.Type = "dois"
metadata.Data.Attributes.DOI = doi
metadata.Data.Attributes.Title = title
payload, _ := json.Marshal(metadata)
req, _ := http.NewRequest("POST", "https://api.test.datacite.org/dois", bytes.NewBuffer(payload))
req.Header.Set("Content-Type", "application/vnd.api+json")
req.SetBasicAuth("USERNAME", "PASSWORD")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
return fmt.Errorf("Registration error: %s", resp.Status)
}
return nil
}
4. Updating and managing
To update a registered DOI, you can send an HTTP PUT request to the same endpoint:
// Similar to the previous function but using PUT method
req, _ := http.NewRequest("PUT", "https://api.test.datacite.org/dois/10.1234/xyz123", bytes.NewBuffer(payload))
5. Resolving a DOI
DOIs can be resolved with a simple redirect using https://doi.org/
. For example:
package main
import (
"fmt"
"net/http"
)
func resolveDOI(doi string) error {
url := fmt.Sprintf("https://doi.org/%s", doi)
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
fmt.Println("Redirected to:", resp.Request.URL)
return nil
}
Conclusion
Generating and managing a DOI in Go is relatively straightforward but requires attention when building metadata and interacting with official APIs. For production use, it’s essential to handle authentication securely and comply with the registering agency’s specifications.