当前位置: 首页 > 科技观察

怎么知道某个 API 是在哪个 Go 版本添加的?这个功能如何实现的

时间:2023-03-19 00:55:51 科技观察

我如何知道API被添加到哪个Go版本中?这个功能是如何实现的呢?因为Go的兼容性很好,所以很多人不太关心Go的具体版本。但是,有时可能会涉及版本问题。例如,如果要使用strings.Builder,Go版本必须>=1.10,但是下面的代码在Go1.10中编译失败。packagemainimport("fmt""strings")funcmain(){varbstrings.Builderb.WriteString("polarisxu")fmt.Println(b.Cap())}编译会报错:$goversiongoversiongo1.10.8darwin/amd64$gorunmain。go#command-line-arguments./main.go:11:15:b.Capundefined(typestrings.BuilderhasnofieldormethodCap)暗示strings.Builder类型没有Cap字段或方法。那么,你知道标准库中的哪些API是在什么版本引入的吗?或者更实际一点,我当前的版本是否可以使用API。01在Go官网获取最新稳定版标准库文档的常见方式有两种。从Go1.11版本开始,在标准库中,每个类型、函数或方法都增加了版本信息。如果没有,则说明Go1.0可用。具体问题参见:https://github.com/golang/go/issues/5778。但是目前还没有常量和变量的版本信息。具体问题参见:https://github.com/golang/go/issues/29204。第二种方法不是看具体API对应的版本,而是至少知道自己当前使用的Go版本是否有某个API。这是pkg.go.dev,具体是通过这个网站https://pkg。go.dev/std?tab=versions选择你对应的版本,然后查看是否有对应的API。当然,如果你使用像GoLand这样的编辑器,它会自动提示是否有某个API。02标准库展示版本是如何实现的好奇心很重要,这是学习的动力之一。看到官网标准库显示版本信息,就想看看是怎么实现的。如何找到实现的代码?我第一反应是看标准库注释里有没有写。//ABuilderisusedtoefficientlybuildastringusingWritemethods.//itminimizesmemorycopying.Thezerovalueisreadytouse.//Donotcopyanon-zeroBuilder.typeBuilderstruct{addr*Builder//ofreceiver,todetectcopiesbyvaluebuf[]byte}没有看到任何版本相关的信息。这个时候怎么找?我的方法是这样的。1)检查页面上的元素,见1.10节点。2)Go官网源码在这里:https://github.com/golang/website,在源码中搜索Addedin,找到package.html模板文件。3)上图中,$since变量表示Go版本,通过since函数获取:`{{.PDoc.ImportPath}}`,显然这是自定义模板函数,所以找找看。没有找到网站项目,所以去tools[1]项目:因为godoc在这个项目里。通过这个可以找到sinceVersionFunc所在的文件:versions.go,然后可以找到如下代码:){varerrerrorc.pkgAPIInfo,err=parsePackageAPIInfo()iferr!=nil{//TODO:considermakingthisfatal,aftertheGo1.11cycle.log.Printf("godoc:errorparsingAPIversionfiles:%v",err)}}funcparsePackageAPIInfo()(apiVersions,error){varapiGlobstringifos.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)iferr!=nil{returnnil,err}vp:=new(versionParser)for_,f:=rangefiles{iferr:=vp.parseFile(f);err!=nil{returnil,err}}returnvp.res,nil}从上面的代码可以看出,版本信息是通过读取api/go*得到的。GOROOT下的txt文件。api目录中的这些文件维护每个版本中添加的内容。从这些文件中读取的最终内容将由以下类型表示://pkgAPIVersionscontainsinformationaboutwhichversionofGoadded//certainpackagesymbols.////OnlythingsaddedafterGo1aretracked.Versionstringsareofthe//form"1.1","1.2",etc.typepkgAPIVersionsstruct{typeSincemap[string]string//"Server"->"1.7"methodSincemap[string]map[string]string//"*Server"->"Shutdown"->1.8funcSincemap[string]string//"NewServer"->"1.7"fieldSincemap[string]map[string]string//"ClientTrace"->"Got1xxResponse"->"1.11"}这里有类型、方法、函数和(类型)字段,但是没有变量和常量,也就是说变量和常量的版本号显示还没有实现。最后在网站项目的main函数中有一句://InitializetheversioninfobeforereadTemplates,其中保存//themapvalueinamemethodvalue.corpus.InitVersionInfo()用于初始化版本信息。03小结希望你在日常生活、学习和工作中多一点好奇心。这篇文章是介绍,内容不重要,希望过程能对你有所启发。当然,如果你打算学习Go语言官网的实现,或许这篇文章会更有帮助。参考文献[1]工具:https://github.com/golang/tools本文转载自微信公众号「polarisxu」,可关注下方二维码。转载本文请联系polarisxu公众号。