golang入门实践(vscode远程开发及调试配置、代码自动提示和跳转)

0、和java一样,go也是跨平台,天生支持Unicode。但是go直接生成可执行文件,性能更高,内存占用少。但是又和java一样,go打出来的二进制包能够扫描到依赖的库,如果库有漏洞,安全扫描会被扫出来。

1、安装、环境配置及术语

从https://golang.google.cn/下载对应的版本。

使用命令行go env可以查看,如下:

复制代码
[lightdb@lightdb-dev ~]$ go env
GO111MODULE=""   #设置是否打开go modules,auto/on/off三个取值,1.13开始默认,1.14开始推荐
GOARCH="amd64"
GOBIN=""    # go install最终拷贝到的目录,一般go程序打成tar.gz分发,所以关系不大,配置的话指向$GOPATH/bin
GOCACHE="/home/lightdb/.cache/go-build"
GOENV="/home/lightdb/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/lightdb/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/lightdb/go"   # 项目的根目录,最重要的环境变量
GOPRIVATE=""
GOPROXY="https://goproxy.cn,direct"   # GOPROXY是用来设置go mod的代理,以英文逗号“,”分割,使Go在后续拉取模块版本时能够脱离传统的VCS方式从镜像站点快速拉取。它拥有一个默认:https://proxy.golang.org,direct,但proxy.golang.org在中国无法访问,所以建议使用goproxy.cn替代
GOROOT="/usr/lib/golang"    # golang的安装目录,跟JAVA_HOME一样
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/golang/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.20.6"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build261630818=/tmp/go-build -gno-record-gcc-switches"
复制代码

hello world验证环境及熟悉目录

复制代码

  [lightdb@lightdb-dev go]$ cd src/example/
  [lightdb@lightdb-dev example]$ go mod init

[lightdb@lightdb-dev go]$ go run src/example/first.go 
123 hello world 65 12.345
[lightdb@lightdb-dev go]$ pwd
/home/lightdb/go
[lightdb@lightdb-dev go]$ 
复制代码
[lightdb@lightdb-dev bin]$ export | grep GO
declare -x GOBIN="//home/lightdb/go/bin"
declare -x GOPATH="/home/lightdb/go"
declare -x GOROOT="//home/lightdb/go/go"

 

 这样脚手架就可以运行了。

[lightdb@lightdb-dev src]$ cd go-web/
[lightdb@lightdb-dev go-web]$ go build ginweb.go   # go build也是个很大的范畴,可以参考https://blog.csdn.net/wan212000/article/details/124288970

相关的报错及原因和解决办法如下:

复制代码
[lightdb@lightdb-dev go]$ go build
go: go.mod file not found in current directory or any parent directory; see 'go help modules'
[lightdb@lightdb-dev go]$ go mod init   # 理论上go mod init即可
go: cannot determine module path for source directory /home/lightdb/go (outside GOPATH, module path must be specified)

Example usage:
    'go mod init example.com/m' to initialize a v0 or v1 module
    'go mod init example.com/m/v2' to initialize a v2 module

Run 'go help mod init' for more information.
[lightdb@lightdb-dev go]$ go mod init example.com/m   # 可以提前预建目录,这样cd dir; go mod init即可,不用指定名称
go: creating new go.mod: module example.com/m
go: to add module requirements and sums:
    go mod tidy
[lightdb@lightdb-dev go]$ go build
$GOPATH/go.mod exists but should not    # 使用go module模块化机制后,go.mod需要放在具体的模块中而非在GOPATH目录下,如$GOPATH/src/example/go.mod,再运行即可
[lightdb@lightdb-dev go]$ go install
$GOPATH/go.mod exists but should not
复制代码
[lightdb@lightdb-dev go]$ go run src/go-web/ginweb.go 
src/go-web/ginweb.go:7:2: no required module provides package github.com/gin-gonic/gin: go.mod file not found in current directory or any parent directory; see 'go help modules'
src/go-web/ginweb.go:5:2: package tool/controller is not in GOROOT (/usr/lib/golang/src/tool/controller)    # 需要在模块的根目录下打包和运行

package first is not in GOROOT (/usr/lib/golang/src/first)   # 在$GOPATH目录下执行  ln -s /usr/lib/golang go

1.1 主要文件

go.mod   Go Modules 的核心文件,包含module、require、replace 和 exclude 4部分。

go.sum   供 Go 命令在构建时判断依赖包是否合法

详见https://zhuanlan.zhihu.com/p/635696935,讲得很清楚了。

1.2 依赖关系

和java一样,go的依赖管理也经过了多次构造,最新为2019年的go mode。

模块是go管理依赖的基本单元,模块由多个package组成。go.mod 文件定义了模块的名称及其依赖包,通过导入路径和版本描述一个依赖。

复制代码
[lightdb@lightdb-dev go]$ go help modules
Modules are how Go manages dependencies.

A module is a collection of packages that are released, versioned, and
distributed together. Modules may be downloaded directly from version control
repositories or from module proxy servers.

For a series of tutorials on modules, see
https://golang.org/doc/tutorial/create-module.

For a detailed reference on modules, see https://golang.org/ref/mod.

By default, the go command may download modules from https://proxy.golang.org.
It may authenticate modules using the checksum database at
https://sum.golang.org. Both services are operated by the Go team at Google.
The privacy policies for these services are available at
https://proxy.golang.org/privacy and https://sum.golang.org/privacy,
respectively.

The go command's download behavior may be configured using GOPROXY, GOSUMDB,
GOPRIVATE, and other environment variables. See 'go help environment'
and https://golang.org/ref/mod#private-module-privacy for more information.
复制代码

1.3 golang工具链

  从Go 1.21开始,Go发行版由一个go命令和一个捆绑的Go工具链组成,后者是标准库以及编译器、汇编器和其他工具。go命令可以使用其捆绑的Go工具链以及它在本地PATH或根据需要下载的其他版本。正在使用的Go工具链的选择取决于GOTOOLCHAIN环境设置和主模块的go.mod文件或当前工作区的go.work文件中的go和工具链行。当您在不同的主模块和工作区之间移动时,正在使用的工具链版本可能会有所不同,就像模块依赖版本一样。 

  如果指定的工具链版本和go版本不一致,则会出现version "go1.23.3" does not match go tool version "go1.23.4"错误,工具链版本太新(各种原因都可能导致)。更新GOTOOLCHAIN为go版本,删除各种go.mod、go.work中的toolchain行(以为它比go行的优先级更高),删除GOPATH、GOROOT下的pkg,重新编译即可。

  即:在标准配置中,当工具链至少与主模块或工作区中的go或工具链行一样新时,go命令使用其自己的捆绑工具链。例如,当在表示go1.21.0的主模块中使用与Go1.21.3捆绑的go命令时,go命令使用Go1.21.3。当go或工具链行比捆绑的工具链更新时,go命令运行较新的工具链。例如,当在表示go1.21.9的主模块中使用与Go1.21.3捆绑的go命令时,go命令会查找并运行Go1.21.9。它首先在PATH中查找名为go1.21.9的程序,否则会下载并缓存Go1.21.9工具链的副本。可以禁用这种自动工具链切换,但在这种情况下,为了更精确的向前兼容性,go命令将拒绝在其中go行需要更新版本的Go的主模块或工作区中运行。也就是说,go行设置使用模块或工作区所需的最低Go版本。

  go: module golang.org/x/tools/gopls@v0.17.1 requires go >= 1.23.1 (running go 1.22.10; GOTOOLCHAIN=go1.22.10)

  将GOTOOLCHAIN设置为和go的版本一样即可。尝试降级gopls不可行,即使执行了go install golang.org/x/tools/gopls@v0.16.0到了指定版本,还是报该错。

go toolchain原理解密

2、IDE配置(vscode为例)及调试

  vscode支持远程开发和本地开发,attach/launch都一样,都支持本地和远程。所以除非要访问linux资源,否则直接windows开发也可以,这和c/c++语言需要依赖很多posix兼容库如pthread.h/uinstd.h/sys/select.h等具有很大的差别。

2.1 工程结构推荐

   一般来说,一个公司多个模块,下面的结构就行。

复制代码
GOPATH  #环境变量配置
	bin
	pkg
    src
        com.xxx    顶级域名作为区分,便于和三方引入包保持一致
            lightdb
                main.go
                base
                service1
                service2
            unisql
                main.go
                base
                service1
                service2
            infra
                module1
                module2
复制代码

   go以包为组织单位,虽然分目录,但包名和目录名不一定要相同(只是习惯上最后一层相同),而且包是单层如packageName而非com.xxx.packageName。一个文件夹下的所有文件必须具有相同的包名声明。

  import的是路径名而非包名(因为一个目录下的所有文件需要声明为一个包,所以import目录就相当于import包),引用的是GOPATH(跟CLASSPATH很像)开始的相对路径。需要注意的是如果目录里面有子目录,则不是同一个包,这个和java是一样的。

  如果多个目录下存在同名的package(这可是必不可免的),需要在import这些目录时为每个目录指定一个package的别名。

2.3.1 大型工程编译

对于大型工程,推荐使用makefile进行编译,如下:

 

复制代码
BINARY=myapp
GOOS ?= $(shell go env GOOS)
GOARCH ?= $(shell go env GOARCH)

build-linux:
    GOOS=linux GOARCH=amd64 go build -o $(BINARY)-$(GOOS)-$(GOARCH)

build-osx:
    GOOS=darwin GOARCH=amd64 go build -o $(BINARY)-$(GOOS)-$(GOARCH)
复制代码

 

make build-linux

 

2.2、代码辅助、跳转及格式化配置

  安装gopls (Go languageserver),go插件。正确的设置GOPATH和GOROOT,最好GOTOOLCHAIN也设置。

 

2.3、debug和attach配置

 安装手册插件。然后安装Go Outliner(outline显示函数列表)

 

 go get -u github.com/go-delve/delve/cmd/dlv 执行后还是这个报错。

到 launch.json 文件设置 "--check-go-version=false",这个错倒是不报了,但是堆栈报错如下:

 ...

 ....

 安装指定版本的dlv,如1.23后,vscode调试正常。

复制代码
[lightdb@hs199 unisql_cli]$ go install github.com/go-delve/delve/cmd/dlv@v1.23.0
go: downloading github.com/go-delve/delve v1.23.0
go: downloading github.com/sirupsen/logrus v1.9.3
go: downloading github.com/spf13/cobra v1.7.0
go: downloading golang.org/x/sys v0.17.0
go: downloading github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62
go: downloading golang.org/x/arch v0.6.0
go: downloading github.com/hashicorp/golang-lru v1.0.2
go: downloading github.com/cilium/ebpf v0.11.0
go: downloading go.starlark.net v0.0.0-20231101134539-556fd59b42f6
go: downloading github.com/cpuguy83/go-md2man/v2 v2.0.2
[lightdb@hs199 unisql_cli]$ dlv version
Delve Debugger
Version: 1.23.0
Build: $Id: e673f2da02185a1c2b6dea52842b0a8c7e7a03b9 $
复制代码

 

2.3.1 配置launch.json
复制代码
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "gotest",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "program": "/home/lightdb/zjhua-dev-src/LTSQL/unisql/sql-convert-runtime-go/unisql_cli/main.go",
            "dlvFlags": [
                "--check-go-version=false"
            ],
            "env": {
                "GOPATH": "/home/lightdb/gpath"
            },
            "args": [],
            "showLog": true
        }
    ]
}
复制代码

 

2.3.2 标准库和三方库能够跳转,业务代码无法跳转,如下:

原因:vscode识别到GOPATH配置的地址不是工程主目录(可通过命令面板go to GOPATH和export | grep GOPATH或go env检查),这是其一。其二,源代码中package名称和目录名不一致,比如package叫做abc/bcc/ffe,目录是xxx/bcc/ffe,就会出现找不到的情况,所以package名最好和路径名保持一致。

Error loading workspace: err: exit status 2: stderr: go: no such tool "compile" : packages.Load error

 

解决方法:

怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev

3、基本概念

每个 Go 程序都是由包构成的。程序从 main 包开始运行。

一个程序中可以有很多main包,这个main包之间无法相互调用,运行时通过go run xxx.go运行。

 按照约定,包名与导入路径的最后一个元素一致(但不强制)。例如,"math/rand" 包中的源码均以 package rand 语句开始。

go里面只有包和函数级别的变量,不存在对象级别。 也就是没有对象。

go里面,类型名在变量名之后,函数返回值在最后(这和java/c++相反),如下:

复制代码
package main

import "fmt"

func add(x int, y int) int {   // 有点类似scala,和java/c都不一样
    return x + y
}

func main() {
    fmt.Println(add(42, 13))
}
复制代码

函数可以返回多值,这个和主流编程语言(如java/c/c++)存在明显的差异,虽然c++在<utility>中支持返回pair带两个值

支持string、bool和无符号类型(和java/c的差别,java不支持无符号,c在17之前不支持布尔,一般模式typedef定义1和0来模拟),类型转换需要强制写,比如int到float,跟postgresql的强类型一样。而且转换是函数调用式的语法target_type(src_val)而不是java/c里面的(target_type) src_val。如下:

复制代码
package main

import (
    "fmt"
    "math"
)

func main() {
    var x, y int = 3, 4
    var f float64 = math.Sqrt(float64(x*x + y*y))  // float64是类型转换
    var z uint = uint(f)
    fmt.Println(x, y, z)
}
复制代码

for/if/else/switch更像是pl/sql的用法加上另外一半的c/c++/java,必须大括号、条件不必强制括号,switch不用带break(因为内置)。支持将某个语句延迟到函数调用(defer)返回后在执行(有点aop after的概念哈)

复制代码
package main

import "fmt"

func main() {
    defer fmt.Println("world")

    fmt.Println("hello")
}
复制代码
这与C++的析构函数十分相似,但是golang的defer只能保证在函数返回前执行,而C++的析构函数可以保证在当前scope退出前执行。

函数内外语句使用差异明显,var和:=

复制代码
package main

import "fmt"

func main() {
    var i, j int = 1, 2
    k := 3   // 函数外的每个语句都必须以关键字开始(var, func 等等),因此 := 结构不能在函数外使用。
    c, python, java := true, false, "no!"

    fmt.Println(i, j, k, c, python, java)
}
复制代码

包成员可见性,大写字母开头为默认导出,小写则不导出,因为大部分开发喜欢默认小写标识符,所以其实对于控制可访问性设计比java/c++可更妥些。

init()函数

和c/c++里面dlopen()加载so文件后自动执行_init()函数一样,init()函数在每次import一个包后自动执行。如果import相互依赖,也不会重复加载,每个包只会被初始化一次。

基本类型以外的高级数据类型

指针(虽然支持,但基本不推荐使用,除非为了效率),go中非简单类型也是传值、并且没有对象java的概念,没有c++的传引用,所以指针不可避免还是会用的多。

结构体(go不支持类,结构体上支持定义方法),结构体上的方法(按照go官方说法:方法只是个带接收者参数的函数)语法略微怪异,如下:

复制代码
package main

import (
    "fmt"
    "math"
)

type Vertex struct {
    X, Y float64
}

func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
    v := Vertex{3, 4}
    fmt.Println(v.Abs())
}
复制代码

支持接口类型(也就是interface的概念)

type Abser interface {
    Abs() float64
}

可变长度数组(切片实现,也支持数组的数组)

在 Go 语言中,数组和切片(slice)是两种不同的数据类型,它们的行为和用途也有所不同。Go 语言设计上更倾向于使用切片而不是直接操作数组,原因如下:


1. 数组是固定长度的,而切片是动态长度的

  • 数组的长度是固定的,定义时需要指定长度(例如 [5]int),且长度不能改变。

  • 切片是动态长度的,它是对数组的抽象,可以动态增长或缩小(例如 []int)。

由于数组的长度固定,直接操作数组会限制灵活性。而切片提供了动态长度的能力,更适合处理不确定长度的数据。


2. 数组是值类型,切片是引用类型

  • 数组是值类型。当数组作为参数传递给函数时,会复制整个数组的内容,这可能会导致性能问题(尤其是数组较大时)。

  • 切片是引用类型。切片本身是一个轻量级的数据结构,包含指向底层数组的指针、长度和容量。当切片作为参数传递时,只会传递切片的元数据(指针、长度和容量),而不会复制底层数组的数据。

复制代码
// 数组示例
func
modifyArray(arr [5]int) { arr[0] = 100 // 修改的是数组的副本 } func main() { a := [5]int{1, 2, 3, 4, 5} modifyArray(a) fmt.Println(a) // 输出: [1 2 3 4 5],原数组未被修改 }
// 切片示例
func modifySlice(s []int) { s[0] = 100 // 修改的是底层数组 } func main() { a := []int{1, 2, 3, 4, 5} modifySlice(a) fmt.Println(a) // 输出: [100 2 3 4 5],原切片被修改 }
复制代码

所以,Go 语言更倾向于使用切片而不是直接操作数组,主要是因为切片提供了更高的灵活性、更好的性能和更方便的操作接口。虽然可以直接操作数组,但在大多数场景下,切片是更合适的选择。

map(原生支持)

支持函数作为参数和返回值(像函数指针或c++里面的function对象),此时函数支持闭包的概念(其实就是中间变量)。

上面两点更像c with object

协程(goroutine和channel):并发的核心是:不用使用共享内存来通信,而是用通信(channel)来共享内存。

5、go自动化回归单元测试

默认情况下,go的单元测试文件放在和源代码一样的目录下,运行go test会对所有的xxx_test.go进行测试,如下:

[lightdb@lightdb-dev go-web]$ go test
?       tool    [no test files]

这是一个比较大的主题,可以参考有赞paas的做法,https://cloud.tencent.com/developer/article/1684515,其中还结合了和sonar报告的集成

https://before80.github.io/go_docs_with_hugo/goBlog/2023/CodeCoverageForGoIntegrationTests/

https://go.dev/blog/integration-test-coverage  go 1.20在go build上增加了-cover选项,支持集成测试统计

对于集成测试,建议搭建一个专门的平台维护用例输出和输入,自动化回归和对比,开发、测试一体化,跟postgresql的make check/make checkworld一样。

java jacoco是一个可以单元测试和集成测试均覆盖的覆盖率工具,支持java agent模式统计。输出也很完整。

https://blog.csdn.net/d_chunyu/article/details/117136293

6、makefile不仅可用于c/c++,还可以用于go。也就是makefile可用于任何linux下的开发,跟语言无关。尤其是go涉及到部分代码使用c/c++开发时更是如此。

7、命令行程序设计

go提供了一个设计命令行程序的框架cobra cli(Kubernetes, Docker, Hugo,pgcenter均基于它)

8、go web开发之gin框架

9、go访问数据库之postgresql,gorm

10、模块分发

go build可以用来打包整个模块

go install将其安装到$GOBIN目录下

https://stackoverflow.com/questions/59741795/how-to-distribute-a-go-module-with-c-dependencies

10.1 go build与go build xxx.go的区别

go build会自动查找目录下main函数,并进行遍历查找所有依赖。go build xxx.go只会编译指定的文件,多个需要穷举列出。前者适合打可执行文件,后者适合打so和普通package。

10.2 go clean

go clean -cache 清理缓存,加-x选项打印明细。

10.3 构建so共享库

  go一共可生成三种类型的so:一种是供c和java调用的标准linux/windows动态共享库,第二种是供go编译时链接的动态库,第三种是插件,本质上也是动态库,只不过只有编译为插件,才能跟c/c++一样通过dlopen加载动态库。

  -buildmode=c-shared,主要供c/java调用。

  -buildmode=shared,go build的时候,使用-linkshared构建。

  -buildmode=plugin,它必须符合下列条件:

  1. 编译的时候 -buildmode=plugin
  2. 包声明必须为 package main
  3. 要导出(函数名或变量名首字母大写)需要被主程序调用的函数或变量,不一定非得是interface,只不过一般来说将其封装为接口,便于管理生命周期和多态可插拔,多为拦截器或hook机制。

  示例可参考https://eli.thegreenplace.net/2021/plugins-in-go/。

10.4 条件编译

  适合于跨平台开发。

  一个源文件中可以有多个 build tags,同一行的逗号隔开的 tag 之间是 逻辑与 的关系,空格隔开的 tag 之间是 逻辑或 的关系, 不同行之间的 tag 是 逻辑与 的关系。

复制代码
# 逻辑或,此源文件只能在 linux 或者 darwin 平台下编译
// +build linux darwin

# 逻辑与,此源文件只能在 linux/amd64 平台下编译
// +build amd64
// +build linux

# 此源文件只能在 linux/386 或者 darwin 平台下编译
// +build linux,386 darwin
复制代码
复制代码
//go:build linux,amd64
// 这个文件只会当目标平台是 Linux amd64 的时候被编译和执行。如果目标是其他平台,这个文件将被忽略。
package main

import "fmt"

func main() {
    fmt.Println("This code only runs on Linux AMD64.")
}
复制代码

  注意://go:build 替代了早期版本 Go 中的 // +build,在 Go 1.17 及以后的版本中推荐使用 //go:build。Go1.19 新增了支持 `go:build unix`。

  编译通过-tags指定,跟c/c++编译的-D宏选项一样。

$ go run -tags debug main.go

  通过 条件编译,可以在构建服务时非常灵活地指定具体的环境、版本、部署方式等参数,真正做到 一套代码,随地编译和运行

  当 go build 或 go test 等命令执行时,它们会检查这些标签来决定哪些文件应该包含在构建过程中。注意:直接go run是不会检查tag的。

11、三方库

  日志:logrus

  kafka:kafka-go ,https://blog.csdn.net/qq_30614345/article/details/131056586,https://zhuanlan.zhihu.com/p/431434480

  json:jsoniter

  orm:https://github.com/go-gorm/gorm

  sql解析:https://github.com/pingcap/parser,当然也可以用postgresql的c语言sql解析器(性能更强),pgpool-ii就是剥离的psotgresql解析器

11.1 标准库和golang/x库

  以下是 golang.org/x 和 Go 内置库的一些主要区别:
1. 来源和维护
  • 内置库:Go 语言的内置库是 Go 语言标准库的一部分,随 Go 语言的安装一同提供,由 Go 语言核心团队进行维护和更新,具有较高的稳定性和兼容性保证,是 Go 语言的基础组成部分,涵盖了网络、文件操作、加密、编码解码等众多常用功能。
  • golang.org/xgolang.org/x 下的包是 Go 语言官方扩展库,由 Go 社区和部分官方团队成员开发和维护,但不是随 Go 语言安装默认提供的,需要通过 go get 等命令手动获取和安装。这些库通常是对标准库的补充,用于提供一些特定领域的功能或实验性的特性。
2. 稳定性和兼容性
  • 内置库:由于是标准库,其 API 在不同版本的 Go 语言中会尽量保持向后兼容,以确保现有代码的稳定性。不过,在一些重大版本更新时,可能会有一些不兼容的改动,但通常会有明确的迁移指南。
  • golang.org/x:这些库的稳定性可能因具体包而异。一些较为成熟和广泛使用的包相对稳定,但也可能会根据社区的反馈和技术发展进行调整和更新,可能会存在 API 变更等情况,在使用时需要关注版本更新和相关说明。
3. 功能范围
  • 内置库:提供了通用的、基础的功能,满足大多数常见的编程需求,例如 net/http 用于 HTTP 服务和客户端开发,fmt 用于格式化输入输出,os 用于操作系统相关操作等。
  • golang.org/x:涵盖了更广泛和多样化的功能,包括一些特定领域的高级功能或新兴技术的支持。例如,golang.org/x/crypto 提供了更多加密算法和安全相关的功能,golang.org/x/net 可能包含一些网络协议的扩展实现或实验性的网络功能,golang.org/x/tools 提供了一些用于代码分析、重构等开发工具相关的功能。
4. 社区参与和发展
  • 内置库:社区对标准库的贡献相对较少,主要由核心团队主导开发和维护。
  • golang.org/x:更开放地接受社区的贡献和参与,社区开发者可以提出新的功能、修复问题和改进现有代码,这使得这些库能够更快地响应新的需求和技术发展,但也可能导致代码质量和稳定性在一定程度上依赖于社区的活跃度和审核机制。

  例如,如果你要进行一些复杂的加密操作,可能会发现 golang.org/x/crypto 中的某些算法或功能比内置库中的更全面和灵活;而对于基本的文件读写操作,使用内置的 os 库就足够了。在项目中选择使用时,需要根据具体需求、稳定性要求以及对社区库的评估来综合考虑。
 

12、docker中go get无法访问代理,如下:

复制代码
[root@lightdb-dev pkg]# docker-compose up
[+] Building 31.4s (9/9) FINISHED                                                                                                                                                   docker:default
 => [helloweb internal] load .dockerignore                                                                                                                                                    0.0s
 => => transferring context: 2B                                                                                                                                                               0.0s
 => [helloweb internal] load build definition from helloweb.build                                                                                                                             0.0s
 => => transferring dockerfile: 439B                                                                                                                                                          0.0s
 => [helloweb internal] load metadata for docker.io/library/golang:1.20                                                                                                                      10.4s
 => [helloweb 1/5] FROM docker.io/library/golang:1.20@sha256:bfc60723228b88180b1e15872eb435cf7e6d8199eae9be77c8dfd8f8079343df                                                                 0.0s
 => [helloweb internal] load build context                                                                                                                                                    0.0s
 => => transferring context: 33B                                                                                                                                                              0.0s
 => CACHED [helloweb 2/5] WORKDIR /app                                                                                                                                                        0.0s
 => CACHED [helloweb 3/5] COPY helloweb.go /app                                                                                                                                               0.0s
 => CACHED [helloweb 4/5] RUN go mod init helloweb                                                                                                                                            0.0s
 => ERROR [helloweb 5/5] RUN go get github.com/go-redis/redis                                                                                                                                21.0s
------                                                                                                                                                                                             
 > [helloweb 5/5] RUN go get github.com/go-redis/redis:
20.99 go: module github.com/go-redis/redis: Get "https://proxy.golang.org/github.com/go-redis/redis/@v/list": dial tcp 142.251.43.17:443: connect: connection refused
------
failed to solve: process "/bin/sh -c go get github.com/go-redis/redis" did not complete successfully: exit code: 1
复制代码

解决方法:docker.build中,使用RUN指定GOPROXY,如下:

# 导入依赖的Redis go module
RUN go mod init helloweb
RUN go env -w GO111MODULE=on
RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN go get github.com/go-redis/redis

再运行docker compose up即可。

Golang 程序员开发效率神器汇总!

查看某个模块依赖的包清单

https://blog.csdn.net/aaqq123456654321/article/details/127113393

go性能分析

pgo,pprof

go与c/c++交互 cgo及环境变量

  参见https://mp.weixin.qq.com/s/yYlbSLva--kDN24EO8f3rA。

内存管理

gc

打印堆栈及性能

https://www.51cto.com/article/748837.html

参见:golang学习笔记(基于1.22,持续更新)

posted @   zhjh256  阅读(109)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
历史上的今天:
2023-01-14 lightdb中日期加减
2017-01-14 使用javassist运行时动态重新加载java类及其他替换选择
2017-01-14 mongodb 最佳可视化工具mongobooster
点击右上角即可分享
微信分享提示