Today's Question:  What does your personal desk look like?        GIVE A SHOUT

How to check when an API is introduced in GoLang

  sonic0002        2021-02-07 00:43:24       1,955        0    

Normally people would not pay much attention to which GoLang version is being used as lots of functions are backward compatible. However there are cases where GoLang version does matter as some functions may not be supported by old version of GoLang. For example, strings.Builder is introduced in Go 1.10, but below code would fail to be compiled on Go 1.10.

package main

import (
 "fmt"
  "strings"
)

func main() {
  var b strings.Builder
  b.WriteString("polarisxu")
  fmt.Println(b.Cap())
}

The compilation error is:

$ go version
go version go1.10.8 darwin/amd64
$ go run main.go
# command-line-arguments
./main.go:11:15: b.Cap undefined (type strings.Builder has no field or method Cap)

It prompts that strings doesn't have Cap field or function.

Hence it's very important to know which version an API is introduced before it can be used in some cases. There are a couple of ways to find out which version an API is introduced. 

On GoLang official doc website, there is version number appended for each type, function or method which indicates the version it is introduced. If there is no version information, it indicates it is there since Go 1.0.

The other way is to check whether an API is supported in a specified version of GoLang. This can be checked at https://pkg.go.dev/std?tab=versions. On the site, you can select the GoLang version and then search the specified package and check its fields, types and functions.

Back to the GoLang official website, how does it get the version information of each API? 

In its source code, there is no version information.

// A Builder is used to efficiently build a string using Write methods.
// It minimizes memory copying. The zero value is ready to use.
// Do not copy a non-zero Builder.
type Builder struct {
 addr *Builder // of receiver, to detect copies by value
 buf  []byte
}

Okay, let's check the GoDoc website source code:

Do a search on GoLang language website source code with term "Added in". Can find it is defined in website/content/static/package.html

The version number is derived from $since,  it is mapping to a template function {{.PDoc.ImportPath}} which is in go tool repository as godoc project is residing there.

With the sinceVersionFunc, can find the versions.go file which has below code.

// InitVersionInfo parses the $GOROOT/api/go*.txt API definition files to discover
// which API features were added in which Go releases.
func (c *Corpus) InitVersionInfo() {
 var err error
 c.pkgAPIInfo, err = parsePackageAPIInfo()
 if err != nil {
  // TODO: consider making this fatal, after the Go 1.11 cycle.
  log.Printf("godoc: error parsing API version files: %v", err)
 }
}

func parsePackageAPIInfo() (apiVersions, error) {
 var apiGlob string
 if os.Getenv("GOROOT") == "" {
  apiGlob = filepath.Join(build.Default.GOROOT, "api", "go*.txt")
 } else {
  apiGlob = filepath.Join(os.Getenv("GOROOT"), "api", "go*.txt")
 }

 files, err := filepath.Glob(apiGlob)
 if err != nil {
  return nil, err
 }

 vp := new(versionParser)
 for _, f := range files {
  if err := vp.parseFile(f); err != nil {
   return nil, err
  }
 }
 return vp.res, nil
}

From this code, it tells the version info is from the api/*.go files in GOROOT's api directory. This directory maintains the newly added items for each version. 

The version info will be read and stored in below struct.

// pkgAPIVersions contains information about which version of Go added
// certain package symbols.
//
// Only things added after Go1 are tracked. Version strings are of the
// form "1.1", "1.2", etc.
type pkgAPIVersions struct {
 typeSince   map[string]string            // "Server" -> "1.7"
 methodSince map[string]map[string]string // "*Server" ->"Shutdown"->1.8
 funcSince   map[string]string            // "NewServer" -> "1.7"
 fieldSince  map[string]map[string]string // "ClientTrace" -> "Got1xxResponse" -> "1.11"
}

This struct defines type, method, func and field information but no constant and variable version information. This means the version information for constant and variable are not implemented yet.

The version information is initialized in website's main() function with below statement.

// Initialize the version info before readTemplates, which saves
// the map value in a method value.
corpus.InitVersionInfo()

With this, we know that the version info is maintained in GOROOT's api directory.

Hope this helps you understand more about the API version info in GoLang.

Reference: æ€Žä¹ˆçŸ¥é“某个 API 是在哪个 Go 版本添加的? (toutiao.com)

GO TOOL  API VERSION  GOLANG 

Share on Facebook  Share on Twitter  Share on Weibo  Share on Reddit 

  RELATED


  0 COMMENT


No comment for this article.