คำสั่งบรรทัดคำสั่ง

คำสั่งใน Go ประกอบด้วยชุดเครื่องมือทั้งหมด ซึ่งครอบคลุมการจัดทำเอกสาร การจัดรูปแบบ การตรวจสอบโค้ด การคอมไพล์ การทดสอบ การจัดการ dependencies และอื่น ๆ อีกมากมาย
bug รายงานช่องโหว่
build คอมไพล์แพ็กเกจและ dependencies
clean ลบไฟล์ object
doc แสดงเอกสารจากซอร์สโค้ด
env ดูข้อมูลตัวแปรสภาพแวดล้อมของ Go
fix แก้ไขปัญหาความเข้ากันได้ของ API เนื่องจากเวอร์ชัน go เปลี่ยนแปลง
fmt จัดรูปแบบซอร์สโค้ด
generate สร้างโค้ด
get เพิ่ม dependencies
install ติดตั้งและคอมไพล์แพ็กเกจ
list คำสั่งแสดงรายการแพ็กเกจ/โมดูล
mod คำสั่งจัดการโมดูล
work คำสั่งจัดการ workspace
run คอมไพล์และรัน
test ทดสอบ
tool รันเครื่องมือ go ที่ระบุ
version แสดงข้อมูลเวอร์ชันของ go
vet สแกนและรายงานปัญหาที่อาจมีในซอร์สโค้ดบทความนี้อธิบายการใช้งานอย่างง่ายเท่านั้น เนื้อหาทั้งหมดอ้างอิงจากเอกสารทางการ หากต้องการเรียนรู้รายละเอียดเพิ่มเติมสามารถไปที่ cmd/go
help
คำสั่งแรกที่ต้องรู้จักคือคำสั่ง help ซึ่งสามารถอ่านวิธีการใช้งานของคำสั่งได้ มีสองวิธีใช้งาน หากต้องการรับข้อมูลการใช้งานแบบย่อ สามารถเพิ่มแฟลก -h หลังคำสั่งที่ต้องการ เช่น
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.go จะแสดงวิธีการใช้งานของคำสั่งนั้นอย่างกระชับ และยังแจ้งว่าหากต้องการข้อมูลรายละเอียดเพิ่มเติมต้องใช้คำสั่ง help
$ go help env
usage: go env [-json] [-u] [-w] [var ...]
Env prints Go environment information.
By default env prints information as a shell script
(on Windows, a batch file). If one or more variable
names is given as arguments, env prints the value of
each named variable on its own line.
The -json flag prints the environment in JSON format
instead of as a shell script.
The -u flag requires one or more arguments and unsets
the default setting for the named environment variables,
if one has been set with 'go env -w'.
The -w flag requires one or more arguments of the
form NAME=VALUE and changes the default settings
of the named environment variables to the given values.
For more about environment variables, see 'go help environment'.การใช้คำสั่ง help อย่างเชี่ยวชาญจะช่วยให้คุณได้รับข้อมูลเกี่ยวกับคำสั่งมากมาย
doc
$ go doc -h
Usage of [go] doc:
go doc
go doc <pkg>
go doc <sym>[.<methodOrField>]
go doc [<pkg>.]<sym>[.<methodOrField>]
go doc [<pkg>.][<sym>.]<methodOrField>
go doc <pkg> <sym>[.<methodOrField>]
For more information run
go help doc
Flags:
-C dir
change to dir before running command
-all
show all documentation for package
-c symbol matching honors case (paths not affected)
-cmd
show symbols with package docs even if package is a command
-short
one-line representation for each symbol
-src
show source code for symbol
-u show unexported symbols as well as exportedคำสั่ง doc จะแสดงเอกสารประกอบสำหรับแพ็กเกจ ค่าคงที่ ฟังก์ชัน ประเภท ตัวแปร เมธอด หรือแม้แต่ฟิลด์ของโครงสร้างที่ระบุ เมื่อไม่ระบุพารามิเตอร์ใด ๆ จะแสดงความคิดเห็นของแพ็กเกจปัจจุบัน
$ go docสามารถระบุเพื่อดูแพ็กเกจใดแพ็กเกจหนึ่งได้ เช่น ดูเอกสารของแพ็กเกจ runtime
$ go doc runtime
package runtime // import "runtime"
Package runtime contains operations that interact with Go's runtime system,
such as functions to control goroutines. It also includes the low-level type
information used by the reflect package; see reflect's documentation for the
programmable interface to the run-time type system.
......หรือดูประเภทใดประเภทหนึ่ง
$ go doc unsafe.Pointer
package unsafe // import "unsafe"
type Pointer *ArbitraryType
Pointer represents a pointer to an arbitrary type. There are four special
operations available for type Pointer that are not available for other
types:
- A pointer value of any type can be converted to a Pointer.
- A Pointer can be converted to a pointer value of any type.
- A uintptr can be converted to a Pointer.
- A Pointer can be converted to a uintptr.
...หรือดูฟังก์ชันใดฟังก์ชันหนึ่ง
$ go doc runtime.GC
package runtime // import "runtime"
func GC()
GC runs a garbage collection and blocks the caller until the garbage
collection is complete. It may also block the entire program.มีแฟลกที่ใช้บ่อยดังนี้
-uดูประเภทส่วนตัว-allดูเอกสารทั้งหมดของแพ็กเกจที่ระบุ-shortแสดงคำอธิบายแบบย่อหนึ่งบรรทัด-srcแสดงซอร์สโค้ด-cmdแสดงเอกสารโค้ดภายในแพ็กเกจที่เป็นคำสั่ง go
เช่น ดูตัวแปร runtime.inf ซึ่งเป็นตัวแปรที่ไม่เปิดเผย
$ go doc -u runtime.inf
package runtime // import "runtime"
var inf = float64frombits(0x7FF0000000000000)การใช้คำสั่ง doc อย่างเหมาะสมจะช่วยให้คุณอ่านเอกสารได้สะดวกขึ้น
อีกวิธีหนึ่งในการอ่านเอกสารคำสั่งคือการอ่านซอร์สโค้ด เนื่องจากเอกสารของคำสั่งบางคำสั่งไม่ได้เขียนอย่างละเอียด แต่ในซอร์สโค้ดจะมีคำอธิบายที่ค่อนข้างละเอียด เนื่องจากคำสั่งเหล่านี้เขียนด้วย go ทั้งหมด การอ่านจึงสะดวกมาก คำสั่งเหล่านี้อยู่ในแพ็กเกจ src/cmd แต่ละซับแพ็กเกจคือคำสั่งแยกต่างหาก จุดเริ่มต้นอยู่ที่ไฟล์ cmd/go/main.go
func init() {
base.Go.Commands = []*base.Command{
bug.CmdBug,
work.CmdBuild,
clean.CmdClean,
doc.CmdDoc,
envcmd.CmdEnv,
fix.CmdFix,
fmtcmd.CmdFmt,
generate.CmdGenerate,
modget.CmdGet,
work.CmdInstall,
list.CmdList,
modcmd.CmdMod,
workcmd.CmdWork,
run.CmdRun,
test.CmdTest,
tool.CmdTool,
version.CmdVersion,
vet.CmdVet,
help.HelpBuildConstraint,
help.HelpBuildmode,
help.HelpC,
help.HelpCache,
help.HelpEnvironment,
help.HelpFileType,
modload.HelpGoMod,
help.HelpGopath,
get.HelpGopathGet,
modfetch.HelpGoproxy,
help.HelpImportPath,
modload.HelpModules,
modget.HelpModuleGet,
modfetch.HelpModuleAuth,
help.HelpPackages,
modfetch.HelpPrivate,
test.HelpTestflag,
test.HelpTestfunc,
modget.HelpVCS,
}
}ที่นี่คุณจะพบคำสั่งย่อยทั้งหมดของ go และข้อมูลเอกสารช่วยเหลือ
bug
$ go help bug
usage: go bug
Bug opens the default browser and starts a new bug report.
The report includes useful system information.คำสั่งนี้ไม่มีพารามิเตอร์หรือแฟลกใด ๆ จะใช้เบราว์เซอร์เริ่มต้นของคุณเพื่อเข้าถึงหน้า issue ของรีพอสิทอรี github.com/golang/go เพื่อสะดวกในการรายงานข้อบกพร่อง นอกเหนือจากนี้ไม่มีฟังก์ชันอื่นใด
version
สามารถดูข้อมูลเวอร์ชันของ go ปัจจุบันผ่านคำสั่ง version
$ go version -h
usage: go version [-m] [-v] [file ...]เมื่อรันโดยไม่มีพารามิเตอร์ใด ๆ จะแสดงเวอร์ชันของภาษา go ปัจจุบัน
$ go version
go version go1.21.0 windows/amd64ยังรับพาธไฟล์เป็นพารามิเตอร์ จะแสดงเวอร์ชัน go ที่ใช้เมื่อคอมไพล์ไฟล์ไบนารีทั้งหมดที่สามารถระบุได้ที่พาธนั้น
$ go version -v ./
buf.exe: go1.20.2
cobra-cli.exe: go1.21.0
dlv.exe: go1.20.2
goctl.exe: go1.20.2
goimports.exe: go1.20.2
golangci-lint.exe: go1.20.2
gopls.exe: go1.19.3
kratos.exe: go1.20.2
main.exe: go1.19.1
protoc-gen-go-grpc.exe: go1.20.2
protoc-gen-go-http.exe: go1.20.2
protoc-gen-go.exe: go1.20.2
protoc-gen-openapi.exe: go1.20.2
swag.exe: go1.21.0
wire.exe: go1.21.0พารามิเตอร์ -v ระบุให้คำสั่ง version พยายามแสดงเวอร์ชัน go ของไฟล์ที่ไม่สามารถระบุได้ พารามิเตอร์ -m แสดงข้อมูลโมดูลของไฟล์ไบนารี และพารามิเตอร์การคอมไพล์บางตัว ด้านล่างเป็นตัวอย่างง่าย ๆ
$ go version -v -m wire.exe
wire.exe: go1.21.0
path github.com/google/wire/cmd/wire
mod github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
dep github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k=
dep github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
dep golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b h1:NVD8gBK33xpdqCaZVVtd6OFJp+3dxkXuz7+U7KaVN6s=
build -buildmode=exe
build -compiler=gc
build DefaultGODEBUG=panicnil=1
build CGO_ENABLED=1
build CGO_CFLAGS=
build CGO_CPPFLAGS=
build CGO_CXXFLAGS=
build CGO_LDFLAGS=
build GOARCH=amd64
build GOOS=windows
build GOAMD64=v1go เองก็เป็นไฟล์ไบนารี ในความเป็นจริงเมื่อไม่มีพารามิเตอร์ใด ๆ go version จะแสดงเวอร์ชันภาษา go ของไฟล์ไบนารีของตัวเอง เนื่องจากเครื่องมือทั้งหมดของ cmd/go ถูกใช้งานโดยภาษา go เอง
env
สามารถดูค่าของตัวแปรสภาพแวดล้อม go ทั้งหมดผ่านคำสั่ง env การแก้ไขตัวแปรสภาพแวดล้อมเหล่านี้จะส่งผลต่อพฤติกรรมของเครื่องมือ go
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.รันคำสั่งนี้โดยไม่มีพารามิเตอร์ใด ๆ จะแสดงค่าของตัวแปรสภาพแวดล้อม go ทั้งหมด
$ go env
set GO111MODULE=on
set GOARCH=amd64
...ระบุชื่อตัวแปรสภาพแวดล้อมใดตัวแปรหนึ่งเป็นพารามิเตอร์เพื่อแสดงค่าของตัวแปรนั้นเพียงตัวเดียว
$ go env GO111MODULE
onเพิ่ม -json เพื่อแสดงในรูปแบบ json
$ go env -json
{
"AR": "ar",
"CC": "gcc",
......
}ผ่านแฟลก -w และใช้รูปแบบ var=value เป็นพารามิเตอร์ จะแก้ไขค่าของตัวแปรใดตัวแปรหนึ่งอย่างถาวร
$ go env -w GO111MODULE=onใช้แฟลก -u เพื่อรีเซ็ตตัวแปรใดตัวแปรหนึ่งกลับเป็นค่าเริ่มต้น
$ go env -u GO111MODULEรัน go help environment เพื่อดูคำอธิบายของตัวแปรสภาพแวดล้อมแต่ละตัว
$ go help environment
The go command and the tools it invokes consult environment variables
for configuration. If an environment variable is unset or empty, the go
command uses a sensible default setting. To see the effective setting of
the variable <NAME>, run 'go env <NAME>'. To change the default setting,
run 'go env -w <NAME>=<VALUE>'. Defaults changed using 'go env -w'
are recorded in a Go environment configuration file stored in the
per-user configuration directory, as reported by os.UserConfigDir.
The location of the configuration file can be changed by setting
the environment variable GOENV, and 'go env GOENV' prints the
effective location, but 'go env -w' cannot change the default location.
See 'go help env' for details.
General-purpose environment variables:
GO111MODULE
Controls whether the go command runs in module-aware mode or GOPATH mode.
May be "off", "on", or "auto".
See https://golang.org/ref/mod#mod-commands.
GCCGO
The gccgo command to run for 'go build -compiler=gccgo'.
GOARCH
The architecture, or processor, for which to compile code.
Examples are amd64, 386, arm, ppc64.
GOBIN
The directory where 'go install' will install a command.
GOCACHE
The directory where the go command will store cached
information for reuse in future builds.
......ต่อไปนี้จะแนะนำตัวแปรสภาพแวดล้อมที่ใช้บ่อยบางตัว
GOVERSION
ค่าของตัวแปรสภาพแวดล้อมนี้ขึ้นอยู่กับเวอร์ชันของภาษา go และหมายเลขเวอร์ชันมาจากไฟล์ $GOROOT/VERSION ซึ่งบันทึกเวอร์ชันปัจจุบันและเวลาสร้างของ go
$ cat $GOROOT/VERSION
go1.21.3
time 2023-10-09T17:04:35Zค่าของตัวแปร runtime.Version เหมือนกับค่าของ GOVERSION และตัวแปรสภาพแวดล้อมนี้ไม่สามารถแก้ไขได้
GOENV
ในไดเรกทอรี $GOROOT จะมีไฟล์การตั้งค่าเริ่มต้นชื่อ go.env
$ cat $GOROOT/go.env
# This file contains the initial defaults for go command configuration.
# Values set by 'go env -w' and written to the user's go/env file override these.
# The environment overrides everything else.
# Use the Go module mirror and checksum database by default.
# See https://proxy.golang.org for details.
GOPROXY=https://proxy.golang.org,direct
GOSUMDB=sum.golang.org
# Automatically download newer toolchains as directed by go.mod files.
# See https://go.dev/doc/toolchain for details.
GOTOOLCHAIN=autoรูปแบบของมันคือ key=value อย่างง่าย ค่าของตัวแปรสภาพแวดล้อมที่แก้ไขผ่านคำสั่ง go env -w key=value จะถูกเขียนลงในไฟล์การตั้งค่า อย่างไรก็ตาม可以不ใช้ไฟล์การตั้งค่าเริ่มต้นก็ได้ ตัวแปรสภาพแวดล้อม GOENV สามารถระบุที่อยู่ของไฟล์การตั้งค่า env ด้วยตนเอง และค่าของตัวแปรสภาพแวดล้อม GOENV สามารถถูกแทนที่ด้วยตัวแปรสภาพแวดล้อมของระบบปฏิบัติการเท่านั้น ไม่สามารถแก้ไขด้วยคำสั่ง go env -w
GOHOSTARCH
แสดงถึงสถาปัตยกรรม CPU ของเครื่องนี้ ใช้สำหรับแสดงเท่านั้น ค่าของตัวแปรสภาพแวดล้อมนี้ไม่ได้อ่านจากไฟล์การตั้งค่า และไม่สามารถแก้ไขได้
GOHOSTOS
แสดงถึงระบบปฏิบัติการของเครื่องนี้ ใช้สำหรับแสดงเท่านั้น ค่าของตัวแปรสภาพแวดล้อมนี้ไม่ได้อ่านจากไฟล์การตั้งค่า และไม่สามารถแก้ไขได้
GOOS
เมื่อคอมไพล์ ค่าของ GOOS จะกำหนดว่าจะคอมไพล์ซอร์สโค้ดเป็นไฟล์ไบนารีของระบบเป้าหมายใด ค่าเริ่มต้นคือ GOHOSTOS ซึ่งก็คือระบบปฏิบัติการของเครื่องนี้ มีตัวเลือกดังนี้
linuxdarwinwindowsnetbsdaixandroid
ระบบปฏิบัติการที่รองรับจริง ๆ ไม่ได้มีเพียงเท่านี้ ใช้คำสั่ง go tool dist list เพื่อดูค่าที่รองรับทั้งหมด
$ go tool dist list | awk -F '/' '{print $1}' | awk '!seen[$0]++'
aix
android
darwin
dragonfly
freebsd
illumos
ios
js
linux
netbsd
openbsd
plan9
solaris
wasip1
windowsGOARCH
เมื่อคอมไพล์ ค่าของ GOARCH จะกำหนดว่าจะใช้สถาปัตยกรรม CPU ใดในการคอมไพล์ ค่าเริ่มต้นคือ GOHOSTARCH ซึ่งก็คือสถาปัตยกรรม CPU ของเครื่องนี้ มีตัวเลือกดังนี้
amd64386armppc64
สถาปัตยกรรมที่รองรับจริง ๆ ไม่ได้มีเพียงเท่านี้ ใช้คำสั่ง go tool dist list เพื่อดูค่าที่รองรับทั้งหมด
$ go tool dist list | awk -F '/' '{print $2}' | awk '!seen[$0]++'
ppc64
386
amd64
arm
arm64
riscv64
wasm
loong64
mips
mips64
mips64le
mipsle
ppc64le
s390xควรทราบว่า GOOS และ GOARCH ไม่สามารถรวมกันได้อย่างอิสระ ระบบปฏิบัติการบางระบบรองรับสถาปัตยกรรม CPU เฉพาะบางตัวเท่านั้น
GOROOT
GOROOT แสดงถึงไดเรกทอรีรากของตำแหน่งติดตั้งภาษา go ค่าของ GOROOT ไม่สามารถแก้ไขโดยตรง และสามารถถูกแทนที่ด้วยตัวแปรสภาพแวดล้อมของระบบปฏิบัติการเท่านั้น
$ ls $GOROOT -1
api
bin
codereview.cfg
CONTRIBUTING.md
doc
go.env
lib
LICENSE
misc
PATENTS
pkg
README.md
SECURITY.md
src
test
VERSIONในไดเรกทอรีรากมีโฟลเดอร์หรือไฟล์ที่สำคัญบางตัวดังนี้
libเก็บ dependencies ปัจจุบันมีเพียงไลบรารีที่มีข้อมูลเขตเวลาของประเทศต่าง ๆ ทั่วโลก อยู่ที่$GOROOT/lib/timeไฟล์ไบนารีที่คอมไพล์แล้วจะไม่มีข้อมูลเขตเวลาเหล่านี้pkgเก็บไลบรารีเครื่องมือและไฟล์เฮดเดอร์ เช่น คำสั่งgo toolจะค้นหาไฟล์ไบนารีของเครื่องมือ go ภายใต้ไดเรกทอรี$GOROOT/pkg/toolbinเก็บไฟล์ไบนารี โดยค่าเริ่มต้นมีเพียงไฟล์ที่รันได้goและgofmtเท่านั้น ควรเพิ่ม$GOROOT/binลงในตัวแปรระบบ มิฉะนั้นจะไม่สามารถใช้คำสั่ง go ได้srcเก็บซอร์สโค้ดของ goVERSIONไฟล์นี้เก็บข้อมูลเวอร์ชันของภาษา gogo.envไฟล์นี้เป็นไฟล์การตั้งค่าenvเริ่มต้น
GOPATH
ค่าเริ่มต้นของ GOPATH คือ $HOME/go ค่าของตัวแปรสภาพแวดล้อมนี้ระบุว่าจะไปหาไฟล์ที่นำเข้าที่ไหนเมื่อแยกวิเคราะห์คำสั่ง import ในยุคแรก ๆ ที่ยังไม่มี gomod GOPATH ใช้สำหรับเก็บไลบรารีบุคคลที่สามต่าง ๆ โดยเฉพาะ มีโครงสร้างดังนี้
GOPATH=/home/user/go
/home/user/go/
src/
foo/
bar/ (go code in package bar)
x.go
quux/ (go code in package main)
y.go
bin/
quux (installed command)
pkg/
linux_amd64/
foo/
bar.a (installed package object)หลังจาก gomod เกิดขึ้น GOPATH ก็เป็นเพียงที่ใช้เก็บ dependencies ที่ดาวน์โหลดด้วย go get และใช้เก็บไฟล์ไบนารีที่ดาวน์โหลดและคอมไพล์ด้วย go install ควรทราบว่าตำแหน่งของ GOPATH ต้องไม่เหมือนกับ GOROOT มิฉะนั้นจะไม่มีผลใด ๆ
$ go env GOBIN
warning: GOPATH set to GOROOT (/home/user/go) has no effectจนถึงขณะที่ผู้เขียนเขียนบทความนี้ เวอร์ชันของภาษา go ได้มาถึง go1.21.3 แล้ว ยกเว้นโปรเจกต์ที่เก่าแก่มาก ๆ โดยพื้นฐานแล้วไม่มีใครใช้ gopath เพื่อจัดการ dependencies อีกต่อไป
GOBIN
GOBIN ใช้สำหรับเก็บไฟล์ไบนารีที่รันได้ของบุคคลที่สามที่ดาวน์โหลดและคอมไพล์ด้วย go install ค่าเริ่มต้นคือ $GOPATH/bin เช่นเดียวกับ $GOROOT/bin ไดเรกทอรีนี้ควรเพิ่มลงในตัวแปรสภาพแวดล้อมของระบบปฏิบัติการ มิฉะนั้นจะไม่สามารถใช้ไฟล์ไบนารีภายใต้ไดเรกทอรี GOBIN ได้
GOMODCACHE
GOMODCACHE แสดงถึงตำแหน่งที่เก็บ dependencies ที่ดาวน์โหลดด้วย go get ค่าเริ่มต้นคือ $GOPATH/pkg/mod รูปแบบการเก็บมีดังนี้
$GOMODCACHE/domain/username/project@verionในไดเรกทอรีระดับเดียวกันจะมีโฟลเดอร์ชื่อ sumdb ใช้สำหรับเก็บข้อมูลที่เกี่ยวข้องกับฐานข้อมูล checksum ของ dependencies
GOCACHE
เก็บข้อมูลแคชสำหรับการคอมไพล์ ค่าเริ่มต้นคือ $HOME/.cache/go-build ภายใต้ไดเรกทอรีนี้จะสร้างไฟล์ README
$ cat $(go env GOCACHE)/README
This directory holds cached build artifacts from the Go build system.
Run "go clean -cache" if the directory is getting too large.
Run "go clean -fuzzcache" to delete the fuzz cache.
See golang.org to learn more about Go.ทุกครั้งที่ build จะสร้างไฟล์จำนวนมาก go จะแคชไฟล์เหล่านี้เพื่อใช้ซ้ำในการคอมไพล์ครั้งต่อไป
GOTEMPDIR
ใช้สำหรับไฟล์ชั่วคราวที่เกิดขึ้นระหว่างการคอมไพล์ เช่น ไฟล์ไบนารีชั่วคราวที่จะรันด้วย go run ค่าเริ่มต้นคือไดเรกทอรีชั่วคราวที่ระบบปฏิบัติการระบุ บน mac หรือ linux คือ /tmp บน windows คือ %TEMP% สามารถแก้ไขเป็นตำแหน่งที่ผู้ใช้ระบุได้
GO111MODULE
ตัวแปรสภาพแวดล้อมนี้แสดงว่าจะใช้วิธีใดในการจัดการ dependencies ของโปรเจกต์ go มีค่าที่ใช้ได้สามค่า
offปิด gomod ใช้ gopath และจะละเว้นไฟล์go.modทั้งหมดonใช้ gomod ไม่ใช้ gopath (ค่าเริ่มต้น)autoตรวจจับอัตโนมัติ หากไฟล์โปรเจกต์มีgo.modจะใช้ gomod ในการจัดการ
TIP
ทำไมถึงเรียกว่า GO111MODULE ไม่เรียก GOMODULE โดยตรง เพราะ gomod เปิดตัวครั้งแรกในเวอร์ชัน go1.11
GOPROXY
ตัวแทนโมดูล go ค่าเริ่มต้นคือ https://proxy.golang.org,direct url คั่นด้วยเครื่องหมายจุลภาค direct หมายถึงใช้ VCS โดยตรงเพื่อข้ามตัวแทนโมดูล จะดำเนินการอันหลังก็ต่อเมื่ออันแรกไม่สามารถเข้าถึงได้还有一个ตัวเลือกที่ใช้ได้คือ off หมายถึงห้ามดาวน์โหลดโมดูลใด ๆ นอกจากนั้น GOPROXY ยังสามารถเป็นที่อยู่ของไฟล์ เช่น
GOPROXY=file://$(go env GOMODCACHE)/cache/downloadผ่าน go get -x สามารถดูคำสั่งที่ดำเนินการในกระบวนการดาวน์โหลด dependencies เพื่อทราบว่ามีการใช้พร็อกซีหรือไม่
$ go get -x github.com/spf13/cast
# get https://goproxy.cn/github.com/@v/list
# get https://goproxy.cn/github.com/spf13/cast/@v/list
# get https://goproxy.cn/github.com/spf13/@v/list
# get https://goproxy.cn/github.com/spf13/@v/list: 404 Not Found (0.118s)
# get https://goproxy.cn/github.com/@v/list: 404 Not Found (0.197s)
# get https://goproxy.cn/github.com/spf13/cast/@v/list: 200 OK (0.257s)
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.info
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.info: 200 OK (0.013s)
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.mod
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.mod: 200 OK (0.015s)
# get https://goproxy.cn/sumdb/sum.golang.org/supported
# get https://goproxy.cn/sumdb/sum.golang.org/supported: 200 OK (0.064s)
# get https://goproxy.cn/sumdb/sum.golang.org/lookup/github.com/spf13/cast@v1.5.1
# get https://goproxy.cn/sumdb/sum.golang.org/lookup/github.com/spf13/cast@v1.5.1: 200 OK (0.014s)
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/0/x079/736
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/0/x079/736: 200 OK (0.016s)
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/1/266
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/0/x068/334
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/0/x068/334: 200 OK (0.023s)
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/1/266: 200 OK (0.028s)
go: downloading github.com/spf13/cast v1.5.1
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.zip
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.zip: 200 OK (0.024s)
go: added github.com/spf13/cast v1.5.1การใช้ตัวแทนโมดูลสามารถเพิ่มความเร็วในการดาวน์โหลดโมดูลได้อย่างมีประสิทธิภาพ สำหรับผู้ใช้ในจีนโดยพื้นฐานแล้วหากไม่ใช้พร็อกซีจะไม่สามารถเข้าถึงตัวแทนทางการเริ่มต้นได้ ปัจจุบันตัวแทนโมดูลบุคคลที่สามที่เปิดเผยและเชื่อถือได้มีดังนี้
https://proxy.golang.com.cnเปิดแหล่งที่มาและให้บริการเวอร์ชันองค์กรhttps://goproxy.cnให้บริการและเปิดแหล่งที่มาโดย Qiniu Cloud
แน่นอนว่ามีแผนการสร้างตัวแทนโมดูลด้วยตนเองแบบเปิดแหล่งที่มา goproxy
GOSUMDB
GOSUMDB ใช้สำหรับตั้งค่าที่อยู่ฐานข้อมูลตรวจสอบ checksum ของไลบรารี dependencies ค่าเริ่มต้นคือ sum.golang.org เมื่อคุณตั้งค่าพร็อกซีแล้ว go จะเข้าถึงฐานข้อมูลตรวจสอบผ่านพร็อกซี
GOPRIVATE
ตัวแปรสภาพแวดล้อม GOPRIVATE ใช้สำหรับตั้งค่าไลบรารีส่วนตัว ไลบรารีที่ตรงกันจะไม่ตรวจสอบผ่าน sumdb และจะไม่ผ่านพร็อกซี จะดาวน์โหลด dependencies ผ่าน VCS โดยตรง รองรับการใช้ wildcard ตั้งค่า คั่นด้วยเครื่องหมายจุลภาค ดังต่อไปนี้ dependencies ทั้งหมดที่ลงท้ายด้วย corp.example.com และชื่อ github.com/gohper/myproject จะไม่ผ่านพร็อกซีและ sumdb
GOPRIVATE=*.corp.example.com,github.com/gohper/myprojectสามารถตั้งค่าผู้ใช้หรือองค์กรใดองค์กรหนึ่งโดยตรง
GOPRIVATE=github.com/gopher,github.com/myorganizationGONOPROXY
ระบุว่า dependencies ใดไม่จำเป็นต้องผ่านพร็อกซี กฎเหมือนกับ GOPRIVATE และจะแทนที่ GOPRIVATE
GONOSUMDB
ระบุว่า dependencies ใดไม่จำเป็นต้องผ่านฐานข้อมูลตรวจสอบ กฎเหมือนกับ GOPRIVATE และจะแทนที่ GOPRIVATE
GOINSECURE
ระบุว่า dependencies ใดใช้ VCS ในการดาวน์โหลดโดยตรง กฎเหมือนกับ GOPRIVATE และจะถูกแทนที่ด้วย GONOPROXY และ GONOSUMDB
GOVCS
ตั้งค่าระบบควบคุมเวอร์ชันของการจัดการโมดูล ค่าเริ่มต้นคือ public:git|hg,private:all สามารถจำกัด VCS ของโดเมนที่ระบุได้ เช่น
GOVCS=github.com:git,evil.com:off,*:git|hgในการจำกัดข้างต้น github ใช้ได้เฉพาะ git, evil.com ไม่อนุญาตให้ใช้ ใช้ | เพื่อแสดง VCS หลายตัว หากไม่มีการจำกัดใด ๆ สามารถตั้งค่าดังนี้
GOVCS=*:allหากไม่อนุญาตให้ใช้ VCS ใด ๆ สามารถตั้งค่าดังนี้
GOVCS=*:offGOWORK
ตั้งค่าว่า workspace เปิดใช้งานหรือไม่ ค่าเริ่มต้นคือว่างหมายถึงเปิดใช้งาน หากตั้งค่าเป็น off จะไม่เปิดใช้งาน และจะละเว้นไฟล์ go.work ทั้งหมด
GOTOOLDIR
ตั้งค่าตำแหน่งที่จะใช้เครื่องมือ go ค่าเริ่มต้นคือ $GOROOT/pkg/tool เครื่องมือเริ่มต้นก็เก็บอยู่ที่ตำแหน่งนี้
GODEBUG
ตั้งค่าตัวเลือกการดีบัก ควบคุมพฤติกรรมการรันบางส่วนของการโปรแกรม go ในรูปแบบคู่คีย์-ค่า เช่น
GODEBUG=http2client=0,http2server=0การตั้งค่าเหล่านี้มีไว้เพื่อความสะดวกในการย้อนกลับของ go เมื่อมีความไม่เข้ากันเกิดขึ้นในระหว่างกระบวนการอัปเดตเวอร์ชัน เช่น ใน 1.21 ไม่อนุญาตให้เกิดสถานการณ์ panic(nil) อีกต่อไป เพื่อจุดประสงค์นี้ go ทางการได้บันทึก GODEBUG History ไว้โดยเฉพาะ ไปที่ GODEBUG เพื่อดูรายละเอียดเพิ่มเติม
CGO_ENABLED
ระบุว่าเปิดใช้งาน cgo หรือไม่ ค่าเริ่มต้นคือ 1 หมายถึงเปิดใช้งาน ตั้งค่าเป็น 0 เพื่อปิด
ตัวแปรสภาพแวดล้อมข้างต้นเป็นตัวแปรที่ใช้บ่อย สำหรับตัวแปรที่ไม่ค่อยได้ใช้จะไม่แนะนำมากเกินไป เช่น CGO, WASM เป็นต้น หากสนใจสามารถศึกษาด้วยตนเอง
build
go รองรับคอมไพเลอร์สองประเภท คือ gccgo และ gc gcc เป็นคอมไพเลอร์ c/c++ แบบเก่า รองรับหลายภาษา รวมถึง go ส่วนหลัง gc ไม่ได้หมายถึง garbage collection แต่หมายถึง go compiler ภาษา go ได้ทำการ bootstrap เสร็จใน go1.5 gc เป็นคอมไพเลอร์ที่เขียนด้วยภาษา go ทั้งหมด ซอร์สโค้ดอยู่ที่แพ็กเกจ cmd/compile เนื่องจากเขียนด้วยการใช้งานภาษา go ทั้งหมด จึงสะดวกมากสำหรับการเรียนรู้และเข้าใจกลไกภายใน โดยค่าเริ่มต้น คอมไพเลอร์ใช้ gc ในการคอมไพล์ ขอแถมเล็กน้อย ตัวดีบักเกอร์ของ go ก็แบ่งเป็นสองประเภทเช่นกัน คือ gdb และ dlv ตัวแรกเป็นดีบักเกอร์ c/c++ แบบเก่า รองรับหลายภาษา รวมถึง go ส่วนหลังเป็นดีบักเกอร์ที่เขียนด้วยภาษา go รองรับภาษา go ได้ดีกว่า และยังเป็นโอเพนซอร์สอีกด้วย แนะนำให้ใช้ตัวหลัง คำสั่ง build ใช้สำหรับคอมไพล์ไฟล์ซอร์ส go เป็นไฟล์ไบนารีที่รันได้ คุณจะสัมผัสประสบการณ์การคอมไพล์ที่รวดเร็วมาก ซึ่งเป็นหนึ่งในลักษณะของภาษา go
$ go build -h
usage: go build [-o output] [build flags] [packages]
Run 'go help build' for details.รับพารามิเตอร์สามตัว หนึ่งคือพาธเอาต์พุตของไฟล์ที่ระบุด้วยแฟลก -o หนึ่งคือแฟลกการคอมไพล์ build flags สำหรับกำหนดพฤติกรรมการคอมไพล์ และสุดท้ายคือแพ็กเกจที่จะคอมไพล์ พารามิเตอร์นี้ต้องอยู่สุดท้าย ด้านล่างเป็นตัวอย่างง่าย ๆ ไม่ได้ใช้แฟลกการคอมไพล์
# Windows
$ go build -o .\bin\golearn.exe golearn
# macOS / Linux
$ go build -o ./bin/golearn golearn./bin/golearn.exe แสดงถึงพาธเอาต์พุต golearn แสดงถึงโมดูลที่จะคอมไพล์ หรืออาจเป็น ไฟล์ entry หรือ โฟลเดอร์ ก็ได้ เช่น ตัวอย่างง่าย ๆ ด้านล่างนี้ใช้ไฟล์ entry main.go เป็นเป้าหมายการคอมไพล์
# Windows
$ go build -o .\bin\golearn.exe main.go
# macOS / Linux
$ go build -o ./bin/golearn main.goในระหว่างการคอมไพล์ จะละเว้นไฟล์ที่ลงท้ายด้วย _test.go ทั้งหมด เนื่องจากตามข้อตกลงแล้วไฟล์เหล่านี้เป็นไฟล์ทดสอบ
นอกจากนี้ คำสั่ง build ยังรองรับแฟลกการคอมไพล์จำนวนมากสำหรับควบคุมพฤติกรรมบางอย่างในระหว่างการคอมไพล์
-xแสดงคำสั่งรายละเอียดในกระบวนการคอมไพล์-nคล้ายกับ-xแต่แตกต่างตรงที่แสดงคำสั่งเหล่านี้เท่านั้น แต่ไม่ดำเนินการจริง-vแสดงแพ็กเกจที่คอมไพล์-pจำนวนการทำงานพร้อมกันในกระบวนการคอมไพล์-aบังคับสร้างใหม่ แม้ว่าจะเป็นล่าสุดแล้ว-compilerระบุว่าใช้คอมไพเลอร์ใดgccgoหรือgcหลังเป็นคอมไพเลอร์ที่เขียนด้วย go-raceเปิดใช้งานการตรวจสอบ race condition-msanเปิดใช้งานการวิเคราะห์หน่วยความจำ-asanเปิดใช้งานการวิเคราะห์ที่อยู่-coverเปิดใช้งานการตรวจสอบความครอบคลุมของโค้ด-buildmodeระบุโหมดการคอมไพล์ มีตัวเลือกarchive,c-archive,c-shared,default,shared,exe,pie,plugin-pgoระบุไฟล์ pgo-trimpathลบคำนำหน้าพาธของไฟล์ซอร์ส เช่น พาธสัมพัทธ์/var/lib/go/src/main.goหลังลบแล้วชื่อไฟล์ที่ได้รับผ่านruntimeในขณะรันจะเป็นพาธสัมพัทธ์เทียบกับพาธโมดูล/main.goเท่านั้น หลังเปิดใช้งาน此项 เวลาในการคอมไพล์จะเพิ่มขึ้นอย่างเห็นได้ชัด ประมาณ 20-40% ขึ้นอยู่กับจำนวนไฟล์-toolexecคำสั่ง go บางคำสั่งที่ดำเนินการก่อนการคอมไพล์ รูปแบบคือ-toolexec 'cmd args'-gcflagsระบุ tag บางตัวของคอมไพเลอร์ gc-gccgoflagsระบุ tag บางตัวของคอมไพเลอร์ gccgo-ldflagsระบุ tag บางตัวของเครื่องมือ link
สำหรับพารามิเตอร์ที่ส่งผ่านเช่น ldflags สามารถส่งพารามิเตอร์เช่น "-help" เพื่อรับค่าที่เป็นไปได้ เช่น
$ go build -ldflags -help
usage: link [options] main.o
-B note
add an ELF NT_GNU_BUILD_ID note when using ELF
-E entry
set entry symbol name
......ข้างต้นเป็นตัวแปรที่ใช้บ่อย สำหรับตัวแปรอื่น ๆ ที่ไม่ค่อยได้ใช้สามารถศึกษาด้วยตนเอง
gcflags
ผ่าน gcflags สามารถส่งพารามิเตอร์บางตัวไปยังคอมไพเลอร์ gc เพื่อควบคุมพฤติกรรมเฉพาะ รูปแบบการใช้งานคือ -gcflags="pattern=args list" args list คือรายการพารามิเตอร์ pattern คือขอบเขตการใช้งาน มีค่าที่ใช้ได้ดังนี้
mainพาธแพ็กเกจระดับบนสุดที่ไฟล์ entry อยู่allโมดูลปัจจุบันและ dependencies ทั้งหมดในโหมดปัจจุบันstdไลบรารีมาตรฐานcmdใช้กับไฟล์ซอร์สทั้งหมดภายใต้แพ็กเกจcmd- wildcard เช่น
.,./...,cmd/...
กฎ pattern นี้ใช้กับแฟลกทั้งหมดที่รองรับรูปแบบนี้ เช่น ldflags ดูค่าที่ใช้ได้ของพารามิเตอร์ผ่านคำสั่งต่อไปนี้
$ go build -gcflags -help
用法:compile [选项] file.go...
-% 调试非静态初始化器
-+ 编译运行时
-B 禁用边界检查
-C 禁用错误消息中的列号打印
-D path
设置本地导入的相对路径
-E 调试符号导出
-I directory
添加目录到导入搜索路径
-K 调试缺失的行号
-L 对于受 //line 指令影响的错误位置,同时显示实际源文件名
-N 禁用优化
-S 打印汇编列表
-V 打印版本并退出
-W 类型检查后调试解析树
......ต่อไปนี้จะแนะนำพารามิเตอร์ที่ใช้บ่อยบางตัว
-Sแสดงรูปแบบ assembly ของโค้ด-Nปิดการคอมไพล์แบบเพิ่มประสิทธิภาพ-mแสดงการตัดสินใจเพิ่มประสิทธิภาพ-lปิดการ inline ฟังก์ชัน-cจำนวนการทำงานพร้อมกันในการคอมไพล์-dwarfสร้างเครื่องหมาย DWARF
เช่น หากต้องการดูรูปแบบ assembly ของโค้ด สามารถใช้พารามิเตอร์ -S และต้องปิดการเพิ่มประสิทธิภาพและการ inline เพื่อคืนรูปแบบเดิมของมัน ดังนี้
$ go build -trimpath -gcflags="-N -l -S" main.go
main.main STEXT size=171 args=0x0 locals=0x58 funcid=0x0 align=0x0
0x0000 00000 (./main.go:9) TEXT main.main(SB), ABIInternal, $88-0
0x0000 00000 (./main.go:9) CMPQ SP, 16(R14)
0x0004 00004 (./main.go:9) PCDATA $0, $-2
0x0004 00004 (./main.go:9) JLS 161
0x000a 00010 (./main.go:9) PCDATA $0, $-1
0x000a 00010 (./main.go:9) PUSHQ BP
0x000b 00011 (./main.go:9) MOVQ SP, BP
0x000e 00014 (./main.go:9) SUBQ $80, SP
0x0012 00018 (./main.go:9) FUNCDATA $0, gclocals·J5F+7Qw7O7ve2QcWC7DpeQ==(SB)
0x0012 00018 (./main.go:9) FUNCDATA $1, gclocals·bDfKCdmtOiGIuJz/x+yQyQ==(SB)
0x0012 00018 (./main.go:9) FUNCDATA $2, main.main.stkobj(SB)
0x0012 00018 (./main.go:10) MOVUPS X15, main..autotmp_0+40(SP)
0x0018 00024 (./main.go:10) LEAQ main..autotmp_0+40(SP), CX
0x001d 00029 (./main.go:10) MOVQ CX, main..autotmp_2+32(SP)ldflags
ผ่าน ldflags สามารถส่งพารามิเตอร์บางตัวไปยัง linker เพื่อควบคุมพฤติกรรมเฉพาะ ดูค่าที่ใช้ได้ทั้งหมดของ ldflags ผ่านคำสั่งต่อไปนี้ มีเกือบยี่สิบหรือสามสิบค่า
$ go build -ldflags -help
usage: link [options] main.o
-B note
add an ELF NT_GNU_BUILD_ID note when using ELF
-E entry
set entry symbol name
-H type
set header type
-I linker
use linker as ELF dynamic linker
-L directory
add specified directory to library path
-R quantum
set address rounding quantum (default -1)
-T int
set the start address of text symbols (default -1)
-V print version and exit
-X definition
add string value definition of the form importpath.name=value
-a no-op (deprecated)
.....พารามิเตอร์ -X ของ ldflags เป็นฟังก์ชันที่มีประโยชน์มาก สามารถกำหนดค่าของตัวแปรสตริงของแพ็กเกจที่ระบุในขณะลิงก์ ผ่านฟังก์ชันนี้ เราสามารถแทรกข้อมูลเมตาบางตัวในขณะคอมไพล์ได้อย่างสะดวก และมันเป็นเพียงตัวแปร ดังนั้นจึงสะดวกในการรับในขณะรัน ด้านล่างเป็นตัวอย่างง่าย ๆ
package main
import "fmt"
var (
Version string
)
func main() {
fmt.Println(Version)
}ดำเนินการคำสั่ง
go build -ldflags "-X main.Version=$(git describe --always)" main.goหลังรันจะแสดง checksum sha1 ของการ commit git
5e3fd7aพารามิเตอร์ที่มีประโยชน์อื่น ๆ มี
-wไม่สร้าง DWARF ซึ่งเป็นข้อมูลที่สะดวกสำหรับการดีบักซอร์สโค้ด-sปิดใช้งานตารางสัญลักษณ์
สองตัวนี้มักใช้ร่วมกัน สามารถลดขนาดของไฟล์ไบนารีหลังคอมไพล์ได้อย่างมีนัยสำคัญ ประมาณ 40%-50% ข้อเสียก็ชัดเจนเช่นกัน ไม่สามารถดีบักได้ ด้านล่างเป็นตัวอย่าง
$ go build -ldflags="-w -s" main.goการคอมไพล์ข้าม
การคอมไพล์ภาษา go มีสองลักษณะใหญ่ ๆ หนึ่งคือเร็ว อีกหนึ่งคือการคอมไพล์ข้าม การคอมไพล์ข้ามหมายถึงสามารถคอมไพล์เป็นโค้ดเป้าหมายของระบบอื่นในท้องถิ่นได้ เช่น บน windows คอมไพล์เป็นไฟล์ไบนารีบน linux หรือ darwin ในทางกลับกันก็เช่นกัน ภาษาที่รองรับการคอมไพล์ข้ามมีมากมาย นี่ไม่ใช่เรื่องแปลก แต่การคอมไพล์ข้ามของภาษา go ง่ายมาก เพียงสองขั้นตอนต่อไปนี้
- ตั้งค่าตัวแปรสภาพแวดล้อม GOOS เลือกระบบปฏิบัติการเป้าหมายของคุณ
- ตั้งค่าตัวแปรสภาพแวดล้อม GOARCH เลือกสถาปัตยกรรม CPU เป้าหมายของคุณ
- ใช้
go buildในการคอมไพล์ตามปกติ
กระบวนการทั้งหมดสั้นมาก ไม่ต้องใช้เครื่องมือหรือการตั้งค่าเพิ่มเติม และความเร็วก็เร็วเหมือนปกติ ดังนี้
build_linux:
SET CGO_ENABLED=0
SET GOOS="linux"
SET GOARCH="amd64"
go build -o golearn main.go
build_mac:
SET CGO_ENABLED=0
SET GOOS="darwin"
SET GOARCH="amd64"
go build -o golearn main.go
build_win:
SET CGO_ENABLED=0
SET GOOS="win"
SET GOARCH="amd64"
go build -o golearn.exe main.go
.PHONY: build_linux \
build_mac \
build_winขั้นตอนแรก SET CGO_ENABLED=0 ปิดใช้งาน cgo เมื่อโค้ดของคุณใช้ cgo จะไม่สามารถใช้การคอมไพล์ข้ามได้ตามปกติ ขั้นตอนที่สอง SET GOOS ตั้งค่าระบบเป้าหมาย ตัวเลือกที่มีคือ linux, darwin, windwos, netbsd ขั้นตอนที่สามตั้งค่าสถาปัตยกรรม CPU SET GOARCH ตัวเลือกที่มีคือ amd64, 386, arm, ppc64 ขั้นตอนสุดท้ายคือการคอมไพล์ตามปกติ
การควบคุมการคอมไพล์
คำสั่ง build สามารถบรรลุผลการควบคุมการคอมไพล์ผ่าน tags ซึ่งมีอยู่ในซอร์สโค้ดในรูปแบบคำสั่ง ดูตัวอย่าง ไฟล์ product.go
// +build product
package main
import "fmt"
func main() {
fmt.Println("product")
}ไฟล์ debug.go
// +build debug
package main
import "fmt"
func main() {
fmt.Println("debug")
}ทั้งคู่มีคำสั่ง // +build แสดงว่าจะถูกคอมไพล์ในสถานการณ์ใด รูปแบบพื้นฐานคือ
// +build tag1 tag2
package pkg_nameมีกฎที่ต้องปฏิบัติตามหลายข้อ
//กับ+buildต้องเว้นวรรคหนึ่งช่อง- ต้องอยู่เหนือการประกาศแพ็กเกจ
- ต้องเว้นบรรทัดว่างหนึ่งบรรทัดกับการประกาศแพ็กเกจ
นอกจากนี้ ยังสามารถบรรลุการควบคุมเชิงตรรกะผ่านการเว้นระยะง่าย ๆ ช่องว่างแสดงว่า OR เครื่องหมายจุลภาคแสดงว่า AND ! แสดงว่า NOT เช่น ตัวอย่างด้านล่างนี้
// +build windows linux
package pkg_nameแสดงว่าภายใต้แพลตฟอร์ม windows หรือ linux จะคอมไพล์ไฟล์ปัจจุบันเข้าไป
// +build windows,amd64,!cgo linux,i386,cgo
package pkg_nameตัวอย่างนี้แสดงว่าจะคอมไพล์ก็ต่อเมื่อแพลตฟอร์ม windows สถาปัตยกรรม amd64 และไม่ได้เปิดใช้งาน cgo หรือแพลตฟอร์ม linux สถาปัตยกรรม i386 และเปิดใช้งาน cgo เท่านั้น หากคุณไม่ต้องการให้ไฟล์ใดไฟล์หนึ่งเข้าร่วมการคอมไพล์อย่างง่าย ๆ สามารถใช้ ignore
// +build ignore
package pkg_nameสามารถมีคำสั่งหลายบรรทัด
// +build windows
// +build amd64
package pkg_nameคำสั่งหลายบรรทัดจะประมวลผลในรูปแบบ AND สำหรับแท็กเช่นแพลตฟอร์มและสถาปัตยกรรมเหล่านี้ ในระหว่างการคอมไพล์ go จะส่งผ่านโดยอัตโนมัติ เรายังสามารถส่งแท็กที่กำหนดเองได้ เช่น ใช้สองไฟล์แรกเป็นตัวอย่าง
$ go build -tags="debug" . && ./golearn.exe
debug
$ go build -tags="product" . && ./golearn.exe
productจะเห็นว่าเมื่อส่งแท็กต่างกัน ผลลัพธ์จะต่างกัน จุดประสงค์ของการควบคุมการคอมไพล์ก็บรรลุแล้ว
run
คำสั่ง run กับ build จะคอมไพล์ซอร์สโค้ดเหมือนกัน แต่ต่างกันที่คำสั่ง run จะรันโดยตรงหลังคอมไพล์เสร็จ เพื่อเพิ่มความเร็วในการคอมไพล์ คำสั่ง run จะไม่สร้างข้อมูลดีบักในกระบวนการคอมไพล์ ดังนั้นจึงไม่รองรับการดีบัก และสร้างไฟล์ไบนารีชั่วคราวเท่านั้น โดยปกติเก็บอยู่ในไดเรกทอรี GOTMEPDIR เช่น /temp/go-build2822241271/b001/exe/main.exe
$ go run -h
usage: go run [build flags] [-exec xprog] package [arguments...]
Run 'go help run' for details.ยังรองรับแฟลกการคอมไพล์ของคำสั่ง build และให้พารามิเตอร์ -exec เพื่อระบุว่าโปรแกรมใดใช้รันไฟล์ไบนารี [arguments...] หมายถึงพารามิเตอร์การรันของโปรแกรม ด้านล่างเป็นตัวอย่าง
package main
import (
"fmt"
"os"
)
var (
Version string
)
func main() {
fmt.Println(Version)
fmt.Println(os.Args[1:])
}ใช้ go run รัน
$ go run -ldflags="-X main.Version=$(git describe --always)" main.go hello
5e3fd7a
[hello]โดยทั่วไปแล้วการใช้งานไม่แตกต่างจาก go build มากนัก จึงไม่ขออธิบายเพิ่มเติม
tool
คำสั่ง tool เองไม่มีฟังก์ชันใด ๆ ฟังก์ชันของมันคือเรียกเครื่องมือภายใต้ไดเรกทอรี cmd/ โดยตรง เช่น cmd/compile คือคอมไพเลอร์ที่มาพร้อม ผ่าน go tool สามารถเรียกเครื่องมือเหล่านี้ได้ ไม่ต้องไปดำเนินการไฟล์ไบนารีของเครื่องมือเหล่านี้ด้วยตนเอง
$ go tool -h
usage: go tool [-n] command [args...]ใช้พารามิเตอร์ -n เพื่อพิมพ์พารามิเตอร์คำสั่งทั้งหมดที่รองรับ
$ go tool -n
addr2line
asm
buildid
cgo
compile
covdata
cover
doc
fix
link
nm
objdump
pack
pprof
test2json
trace
vetเครื่องมือเหล่านี้เก็บอยู่ในไดเรกทอรี GOROOT/pkg/tool และจัดกลุ่มเครื่องมือตามระบบปฏิบัติการและสถาปัตยกรรม CPU ดังนี้
$ ls $GOROOT/pkg/tool/windows_amd64/ -1
addr2line.exe*
asm.exe*
buildid.exe*
cgo.exe*
compile.exe*
covdata.exe*
cover.exe*
doc.exe*
fix.exe*
link.exe*
nm.exe*
objdump.exe*
pack.exe*
pprof.exe*
test2json.exe*
trace.exe*
vet.exe*ใช้รูปแบบ go doc cmd/command เพื่อดูวิธีการใช้ของแต่ละคำสั่ง เช่น
$ go doc cmd/compile
Usage:
go tool compile [flags] file...
The specified files must be Go source files and all part of the same package.
The same compiler is used for all target operating systems and architectures.
The GOOS and GOARCH environment variables set the desired target.
Flags:
-D path
Set relative path for local imports.
-I dir1 -I dir2
Search for imported packages in dir1, dir2, etc,
after consulting $GOROOT/pkg/$GOOS_$GOARCH.
-L
Show complete file path in error messages.
...พารามิเตอร์ที่รองรับโดย cmd/compile ก็คือพารามิเตอร์ที่รองรับโดย gcflags ที่กล่าวถึงก่อนหน้านี้ ความแตกต่างระหว่าง go tool compile กับ go build คือ ตัวแรกรับผิดชอบการคอมไพล์เท่านั้น และรับไฟล์เป็นพารามิเตอร์เท่านั้น ตัวหลังสามารถรับโฟลเดอร์ แพ็กเกจ ไฟล์ เป็นพารามิเตอร์ได้ และไม่เพียงแต่ทำการคอมไพล์ซอร์สโค้ดเท่านั้น แต่ยังรับผิดชอบในการลิงก์ไฟล์ ลบไฟล์ที่ไม่จำเป็น ฯลฯ ตัวแรกเป็นส่วนหนึ่งของตัวหลัง เราสามารถพิมพ์คำสั่งที่ดำเนินการในกระบวนการ build
$ go build -n main.go
#
# internal/goarch
#
mkdir -p $WORK\b004\
cat >$WORK\b004\importcfg << 'EOF' # internal
# import config
EOF
"/golang/pkg/tool/windows_amd64/compile.exe" -o "$WORK/b004/_pkg_.a" -trimpath "$WORK/b004=>" -p internal/goarch -std -+ -complete -buildid 3gunEkUExGdhOPa2rFsh/3gunEkUExGdhOPa2rFsh -goversion go1.21.0 -c=4 -nolocalimports -importcfg "$WORK/b004/importcfg" -pack "/golang/src/internal/goarch/goarch.go" "/golang/src/internal/goarch/goarch_amd64.go" "/golang/src/internal/goarch/zgoarch_amd64.go"
"/golang/pkg/tool/windows_amd64/buildid.exe" -w "$WORK/b004/_pkg_.a" # internal
...ในกระบวนการจะเห็นว่ามีส่วน /golang/pkg/tool/windows_amd64/compile.exe นี้คือการเรียกคอมไพเลอร์ นอกจาก compile แล้ว ยังมีเครื่องมืออีกมากมายที่สามารถเรียกได้ คำสั่ง go หลายคำสั่งจริง ๆ แล้วเป็นชื่อเล่นของเครื่องมือเหล่านี้
clean
คำสั่ง clean ใช้สำหรับลบไฟล์ object ที่สร้างขึ้นในระหว่างการคอมไพล์
$ go clean -h
usage: go clean [clean flags] [build flags] [packages]
Run 'go help clean' for details.รองรับแฟลกต่อไปนี้
-iลบไฟล์ archive หรือไฟล์ไบนารีที่สอดคล้องกัน-nพิมพ์คำสั่งที่จะดำเนินการในกระบวนการลบ แต่ไม่ดำเนินการจริง-xพิมพ์คำสั่งที่จะดำเนินการในกระบวนการลบและดำเนินการ-rลบแบบเรียกซ้ำผ่านimport path-cacheลบแคชทั้งหมดที่เกิดจากgo build-testcacheลบแคชการทดสอบทั้งหมดที่เกิดขึ้น-modcacheลบแคชโมดูลที่ดาวน์โหลดทั้งหมด-fuzzcacheลบแคชที่เกิดจากfuzz test
เมื่อใช้ go tool compile จะเป็นการเรียกคำสั่งคอมไพเลอร์โดยตรง ไม่เหมือน go build ที่จะทำการจัดการหลังบ้านมากมาย จะสร้างไฟล์ object เช่น ดำเนินคำสั่งต่อไปนี้
go tool compile -N -S -l main.goจะสร้างไฟล์ชื่อ main.o ใช้คำสั่ง go clean ลบได้ หรือใช้พารามิเตอร์ -n เพื่อพิมพ์คำสั่งที่จะดำเนินการ
$ go clean -n
rm -f golearn golearn.exe golearn golearn.exe golearn.test golearn.test.exe golearn.test golearn.test.exe api api.exe main main.exeลบแคชการคอมไพล์ จะลบแคชการคอมไพล์ที่เกิดขึ้นภายใต้ไดเรกทอรี GOCACHE
$ go clean -cache -n
rm -r /cache/00 /cache/01 /cache/02ลบแคชที่เกิดจาก fuzz test แคชเหล่านี้เก็บอยู่ในไดเรกทอรี GOCACHE/fuzz/ โดยค่าเริ่มต้น
$ go clean -fuzzcache -n
rm -rf /cache/fuzzfix
ภาษา go จนถึงขณะที่เขียนบทความนี้มีอายุสิบปีแล้ว ในกระบวนการอัปเดตและแก้ไขภาษาอย่างต่อเนื่อง ย่อมมีบางปัญหาความไม่เข้ากันเนื่องจาก API เปลี่ยนแปลง คำสั่ง fix เกิดมาเพื่อจุดประสงค์นี้ จะตรวจสอบไฟล์ซอร์สเพื่อหา API ที่ล้าสมัยและแทนที่ด้วย API ใหม่
$ go fix -h
usage: go fix [-fix list] [packages]
Run 'go help fix' for details.รองรับโฟลเดอร์ ชื่อไฟล์ ไดเรกทอรี เป็นพารามิเตอร์ รับแฟลก -fix เพื่อส่งพารามิเตอร์เพื่อระบุว่าจะทำการแก้ไขแบบใด สามารถดูค่าที่ใช้ได้ผ่านคำสั่ง got tool fix -help
$ go tool fix -help
usage: go tool fix [-diff] [-r fixname,...] [-force fixname,...] [path ...]
-diff
display diffs instead of rewriting files
-force string
force these fixes to run even if the code looks updated
-go string
go language version for files
-r string
restrict the rewrites to this comma-separated list
Available rewrites are:
buildtag
Remove +build comments from modules using Go 1.18 or later
cftype
Fixes initializers and casts of C.*Ref and JNI types
context
Change imports of golang.org/x/net/context to context
egl
Fixes initializers of EGLDisplay
eglconf
Fixes initializers of EGLConfig
gotypes
Change imports of golang.org/x/tools/go/{exact,types} to go/{constant,types}
jni
Fixes initializers of JNI's jobject and subtypes
netipv6zone
Adapt element key to IPAddr, UDPAddr or TCPAddr composite literals.
https://codereview.appspot.com/6849045/
printerconfig
Add element keys to Config composite literals.ต่อไปนี้เป็นตัวอย่าง ซอร์สโค้ดใช้แพ็กเกจ golang.org/x/net/context
package main
import (
"fmt"
"golang.org/x/net/context"
)
func main() {
background := context.Background()
fmt.Println(background.Err())
}แก้ไขด้วย go fix แทนที่ด้วยแพ็กเกจ context ในไลบรารีมาตรฐาน เราสามารถใช้คำสั่งต่อไปนี้เพื่อแทนที่
$ go fix -fix context main.goหรือ可以不แทนที่ ดูการเปลี่ยนแปลงของไฟล์ก่อนและหลัง
$ go tool fix -r context -diff main.go
main.go: fixed context
diff main.go fixed/main.go
--- main.go
+++ fixed/main.go
@@ -1,8 +1,8 @@
package main
import (
+ "context"
"fmt"
- "golang.org/x/net/context"
)
func main() {ภาษา go เกิดมาสิบกว่าปีมีพารามิเตอร์แทนที่ได้เพียงเก้าตัว เห็นได้ว่าการรักษาความเข้ากันได้นั้นค่อนข้างดี
fmt
คำสั่ง fmt เป็นเครื่องมือจัดรูปแบบที่มาพร้อมกับภาษา go ใช้สำหรับจัดรูปแบบไฟล์ซอร์สโค้ด go
$ go fmt -h
usage: go fmt [-n] [-x] [packages]
Run 'go help fmt' for details.ดูเอกสารรายละเอียดผ่านคำสั่ง go doc gofmt
$ go doc cmd/gofmt
Gofmt formats Go programs. It uses tabs for indentation and blanks for
alignment. Alignment assumes that an editor is using a fixed-width font.
Usage:
gofmt [flags] [path ...]
The flags are:
-d
Do not print reformatted sources to standard output.
If a file's formatting is different than gofmt's, print diffs
to standard output.
-e
Print all (including spurious) errors.
-l
Do not print reformatted sources to standard output.
If a file's formatting is different from gofmt's, print its name
to standard output.
-r rule
Apply the rewrite rule to the source before reformatting.
-s
Try to simplify code (after applying the rewrite rule, if any).
-w
Do not print reformatted sources to standard output.
If a file's formatting is different from gofmt's, overwrite it
with gofmt's version. If an error occurred during overwriting,
the original file is restored from an automatic backup.gofmt ใช้ tab สำหรับการเยื้อง และใช้ช่องว่างสำหรับการจัดตำแหน่ง โดยค่าเริ่มต้นโค้ดหลังจัดรูปแบบจะแสดงออกทางเอาต์พุตมาตรฐาน ไม่ได้ทับไฟล์ต้นฉบับ คำสั่ง go fmt จริง ๆ แล้วใช้คำสั่ง gofmt เป็นไฟล์ไบนารีแยกต่างหาก อยู่ที่ไดเรกทอรี GOROOT/bin
$ ls $GOROOT/bin -1
go.exe*
gofmt.exe*เพิ่มแฟลก -n ให้กับคำสั่ง go fmt จะทราบว่าคำสั่งที่จะดำเนินการ
$ go fmt main.go
/golang/bin/gofmt.exe -l -w main.goจะเห็นว่า go fmt จริง ๆ แล้วเป็นชื่อเล่นของ gofmt -l -w คำสั่ง gofmt มีพารามิเตอร์ดังนี้
-dแสดงความแตกต่างของไฟล์ก่อนและหลังจัดรูปแบบ-eแสดงข้อผิดพลาดทั้งหมด-lแสดงชื่อไฟล์ที่มีการเปลี่ยนแปลง-rใช้กฎการจัดรูปแบบ-sพยายามทำให้โค้ดง่ายขึ้น-wทับไฟล์ต้นฉบับ หากเกิดข้อผิดพลาดจะคืนค่าสำรอง
สมมติว่ามีไฟล์ต้นฉบับดังนี้
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world!")}ดูการเปลี่ยนแปลงผ่านพารามิเตอร์ -d
$ gofmt -d main.go
diff main.go.orig main.go
--- main.go.orig
+++ main.go
@@ -3,5 +3,5 @@
import "fmt"
func main() {
-fmt.Println("hello world!")}
-
+ fmt.Println("hello world!")
+}พารามิเตอร์ -l จะแสดงชื่อไฟล์ที่จะแก้ไข
$ gofmt -l .
main.goหากมีข้อผิดพลาดทางไวยากรณ์ พารามิเตอร์ -e สามารถแสดงรายละเอียดมากขึ้น
$ gofmt -d -e main.go
main.go:6:27: missing ',' in argument list
main.go:6:28: expected operand, found newline
main.go:7:2: expected ')', found 'EOF'
main.go:7:2: expected ';', found 'EOF'
main.go:7:2: expected ';', found 'EOF'
main.go:7:2: expected '}', found 'EOF'
main.go:7:2: missing ',' in argument list-w จะใช้การแก้ไขกับไฟล์ต้นฉบับ
$ gofmt -l -w .
main.go
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world!")
}คุณจะพบว่าในฐานะเครื่องมือจัดรูปแบบ gofmt ไม่ได้ให้การกำหนดค่าที่กำหนดเองใด ๆ เลย ในขณะที่ตัวจัดรูปแบบ prettify ที่专为美化โค้ด js มันให้การกำหนดค่าจำนวนมากสำหรับจัดรูปแบบโค้ด ที่นี่สามารถสะท้อนทัศนคติของทางการ go อย่าคิดที่จะทำอะไรที่เป็นส่วนตัว ทุกคนควรมีสไตล์โค้ดเหมือนกันอย่างน้อยก็มีข้อดีอย่างหนึ่งคือไม่ต้องปรับตัวกับนิสัยของผู้อื่นเมื่ออ่านโค้ด แต่จริง ๆ แล้วมันยังคงรักษาตัวเลือกที่กำหนดเองไว้หนึ่งตัว คือกฎการแทนที่โค้ดที่จัดรูปแบบแล้ว กฎสามารถกำหนดเองได้ รูปแบบดังนี้
pattern -> replacementเช่น ลบวงเล็บที่ซ้ำซ้อน
(a) -> aดูการเปลี่ยนแปลงของไฟล์
$ gofmt -r "(a) -> a" -d -l .
main.go
diff main.go.orig main.go
--- main.go.orig
+++ main.go
@@ -3,5 +3,5 @@
import "fmt"
func main() {
- fmt.Println(("hello world!"))
+ fmt.Println("hello world!")
}จะเห็นว่า gofmt จะลบวงเล็บที่ซ้ำซ้อนออก
get
คำสั่ง get แน่นอนว่าเป็นคำสั่งที่ใช้บ่อยที่สุดในระหว่างการพัฒนา go ฟังก์ชันของมันคือดาวน์โหลดซอร์สโค้ดของแพ็กเกจที่อยู่ที่ระบุไปยังไดเรกทอรีที่สอดคล้องกับ GOMODCACHE
$ go get -h
usage: go get [-t] [-u] [-v] [build flags] [packages]
Run 'go help get' for details.-uพยายามอัปเดตเวอร์ชันรองและเวอร์ชันแพตช์ของแพ็กเกจ หากเกี่ยวข้องกับการเปลี่ยนแปลงเวอร์ชันหลัก เช่นv1->v2จะไม่อัปเดต-tอัปเดตเวอร์ชัน dependencies ในการทดสอบ-vแสดงแพ็กเกจที่คอมไพล์ จริง ๆ แล้วเป็นพารามิเตอร์หนึ่งของbuild flags
ในยุคแรก ๆ ฟังก์ชันของ go get คล้ายกับ go install จะดาวน์โหลดและคอมไพล์แพ็กเกจเหล่านี้ อย่างไรก็ตาม ด้วยการเกิดขึ้นและความสมบูรณ์ของโมดูล go ฟังก์ชันส่วนนี้ก็ค่อย ๆ ถูกยกเลิกไป คำสั่ง get ในปัจจุบันใช้บ่อยที่สุดสำหรับการดาวน์โหลดและแยกวิเคราะห์ dependencies ของโมดูล go ดังนั้นคุณจะเห็นว่าคำสั่ง go get ยังรองรับแฟลกการสร้างประเภท build flags และหากคุณพยายามใช้ go get นอกโมดูลเหมือนใช้ go install มันจะแจ้งว่าวิธีการใช้นี้ถูกยกเลิกแล้ว
$ go get github.com/wire/wire
go: go.mod file not found in current directory or any parent directory.
'go get' is no longer supported outside a module.
To build and install a command, use 'go install' with a version,
like 'go install example.com/cmd@latest'
For more information, see https://golang.org/doc/go-get-install-deprecation
or run 'go help get' or 'go help install'.ส่วนเหตุผลที่ยังคงรักษาไว้ในคำอธิบายเอกสารก็ไม่ทราบเช่นกัน เมื่อพลิกดูซอร์สโค้ดของคำสั่ง get คุณจะพบว่ามันยังคงรักษา flag เดิมไว้
var (
getD = CmdGet.Flag.Bool("d", true, "")
getF = CmdGet.Flag.Bool("f", false, "")
getFix = CmdGet.Flag.Bool("fix", false, "")
getM = CmdGet.Flag.Bool("m", false, "")
getT = CmdGet.Flag.Bool("t", false, "")
getU upgradeFlag
getInsecure = CmdGet.Flag.Bool("insecure", false, "")
// -v is cfg.BuildV
)กลับเข้าเรื่อง คำสั่ง get จะดาวน์โหลดซอร์สโค้ดของแพ็กเกจที่ระบุไปยังไดเรกทอรี dependencies ส่วนกลางของท้องถิ่น ซึ่งก็คือไดเรกทอรีที่สอดคล้องกับ GOCACHE จากนั้นบันทึกข้อมูลลงในไฟล์ go.mod และ go.sum ไฟล์แรกรับผิดชอบการบันทึกเวอร์ชัน ไฟล์หลังรับผิดชอบการบันทึก checksum sha1 เพื่อความปลอดภัย คำสั่ง get จริง ๆ แล้วอยู่บนพื้นฐานของ VCS ซึ่งก็คือระบบควบคุมเวอร์ชันของท้องถิ่น รองรับต่อไปนี้ทั้งหมด
- git
- hg (Mercurial)
- bzr (Bazaar)
- svn
- fossil
ในนั้น รองรับ git และ hg โดยค่าเริ่มต้น สามารถกำหนดค่าใน GOVCS รูปแบบดังนี้
GOVCS=github.com:git,example.com:hg,*:git|hg,*:allGOVCS รองรับ git และ hg เป็น VCS เท่านั้น อีกสามตัวต้องกำหนดค่าใน GOPRIVATE
คำสั่ง go get มีวิธีการใช้ดังนี้ สามารถใช้ที่อยู่ dependencies เป็นพารามิเตอร์โดยตรง
$ go get golang.org/x/netหรือระบุเวอร์ชัน
$ go get golang.org/x/net@0.17.0ระบุเวอร์ชันล่าสุด
$ go get golang.org/x/net@latestพยายามอัปเดตเวอร์ชัน
$ go get -u golang.org/x/netลบ dependencies ใด dependencies หนึ่ง
$ go get golang.org/x/net@noneข้างต้นใช้สำหรับจัดการ dependencies ทั่วไป ยังสามารถใช้จัดการ dependencies ที่ไม่ธรรมดาได้ เช่น อัปเดตเวอร์ชันของภาษา go
$ go get go@latest
go: updating go.mod requires go >= 1.21.3; switching to go1.21.3
go: downloading go1.21.3 (windows/amd64)
go: upgraded go 1.21.0 => 1.21.3หรือแม้แต่ใช้สำหรับอัปเดตเวอร์ชันของเครื่องมือ go
$ go get toolchain@latestเมื่อคุณใช้ go get อัปเดตเวอร์ชันของ go และเครื่องมือ go มันจะติดตั้งเวอร์ชันใหม่ของ go ภายใต้ไดเรกทอรี GOMODCACHE/golang.org/
$ ls $(go env GOMODCACHE)/golang.org -1
'toolchain@v0.0.1-go1.21.3.windows-amd64'/
x/ตอนนี้แก้ไข GOROOT ด้วยตนเองก็สามารถสลับไปยังเวอร์ชันที่ระบุได้
install
คำสั่ง install คล้ายกับคำสั่ง get ทั้งคู่ใช้สำหรับดาวน์โหลด dependencies ของบุคคลที่สาม แต่ต่างกันที่คำสั่ง get ดาวน์โหลดซอร์สโค้ด ในขณะที่คำสั่ง install จะคอมไพล์ซอร์สโค้ดเป็นไฟล์ไบนารีที่รันได้ของเครื่องนี้ พาธเก็บไฟล์ไบนารีอยู่ในไดเรกทอรี GOBIN ก่อน其次是 GOPATH/bin ฟังก์ชันหลักของคำสั่งนี้ใช้สำหรับดาวน์โหลดเครื่องมือบรรทัดคำสั่งสาธารณะบางตัวของบุคคลที่สาม เนื่องจากความเร็วในการคอมไพล์และความสามารถในการพกพาของภาษา go ไม่จำเป็นต้องดาวน์โหลดไฟล์ไบนารี แต่ดาวน์โหลดซอร์สโค้ดแล้วคอมไพล์ในท้องถิ่น
$ go install -h
usage: go install [build flags] [packages]
Run 'go help install' for details.คำสั่ง install รับแฟลกการสร้างและชื่อแพ็กเกจเป็นพารามิเตอร์ ในกรณีที่เปิดใช้งาน gomod ชื่อแพ็กเกจต้องพกหมายเลขเวอร์ชัน เช่น ดาวน์โหลดดีบักเกอร์ delve
$ go install -x github.com/go-delve/delve/cmd/dlv@latest
# get https://goproxy.cn/github.com/@v/list
# get https://goproxy.cn/github.com/go-delve/delve/cmd/@v/list
# get https://goproxy.cn/github.com/go-delve/delve/cmd/dlv/@v/list
# get https://goproxy.cn/github.com/go-delve/delve/@v/list
# get https://goproxy.cn/github.com/go-delve/@v/list
# get https://goproxy.cn/github.com/@v/list: 404 Not Found (0.014s)
# get https://goproxy.cn/github.com/go-delve/delve/cmd/@v/list: 404 Not Found (0.027s)
# get https://goproxy.cn/github.com/go-delve/delve/cmd/dlv/@v/list: 404 Not Found (0.027s)
# get https://goproxy.cn/github.com/go-delve/delve/@v/list: 200 OK (0.027s)
# get https://goproxy.cn/github.com/go-delve/@v/list: 404 Not Found (0.027s)
WORK=/home/user/tmp/go-build2033992495
mkdir -p $WORK/b001/
cat >/home/user/tmp/go-build2033992495/b001/importcfg.link << 'EOF' # internal
packagefile github.com/go-delve/delve/cmd/dlv=/home/user/.cache/go-build/f1/f11d552287458c0fce625abe50bf928c487064c36bbb1251ad8b1968772c3e4b-d
......
......
mkdir -p /home/wyh/gomod/bin/
mv $WORK/b001/exe/a.out /home/wyh/gomod/bin/dlv
rm -r $WORK/b001/ก่อนอื่นจะดาวน์โหลดซอร์สโค้ดไปยังพาธที่เก็บใน GOMODCACHE จุดนี้เหมือนกับคำสั่ง get จากนั้นสลับไปยังไดเรกทอรีทำงานชั่วคราว คอมไพล์ หลังจากคอมไพล์เสร็จจะย้ายไฟล์ไบนารีไปยังไดเรกทอรี GOPATH/bin สุดท้ายลบโฟลเดอร์ชั่วคราว คำสั่ง install ยังมีข้อจำกัดหนึ่งคือแพ็กเกจที่ดาวน์โหลดต้องเป็นแพ็กเกจ entry ของโปรเจกต์นั้น หมายความว่าต้องมีไฟล์ entry main.go มิฉะนั้นจะแจ้งว่าไม่สามารถติดตั้งได้ เช่น ใช้ go install ดาวน์โหลด gin
$ go install -x github.com/gin-gonic/gin@latest
# get https://goproxy.cn/github.com/@v/list
# get https://goproxy.cn/github.com/gin-gonic/gin/@v/list
# get https://goproxy.cn/github.com/gin-gonic/@v/list
# get https://goproxy.cn/github.com/@v/list: 404 Not Found (0.022s)
# get https://goproxy.cn/github.com/gin-gonic/gin/@v/list: 200 OK (0.027s)
# get https://goproxy.cn/github.com/gin-gonic/@v/list: 404 Not Found (0.028s)
package github.com/gin-gonic/gin is not a main packagegin เป็นไลบรารี dependencies ของเฟรมเวิร์กเว็บ ไม่ใช่เครื่องมือบรรทัดคำสั่ง แน่นอนว่าไม่มีไฟล์ entry ดังนั้นการติดตั้งจะล้มเหลว
list
คำสั่ง list จะแสดงแพ็กเกจที่ตำแหน่งที่ระบุ ทีละบรรทัด และรองรับการเอาต์พุตที่จัดรูปแบบเอง รองรับพารามิเตอร์จำนวนมาก การใช้มันต้องอยู่ในโปรเจกต์ที่รองรับ gomod
$ go list -h
usage: go list [-f format] [-json] [-m] [list flags] [build flags] [packages]
Run 'go help list' for details.พารามิเตอร์ที่รองรับมีดังนี้
-fพารามิเตอร์จัดรูปแบบ-jsonเอาต์พุตในรูปแบบ json-compiledแสดงแพ็กเกจทั้งหมดที่จะถูกคอมไพล์โดยคอมไพเลอร์-depsแสดงชื่อของแพ็กเกจแต่ละแพ็กเกจและ dependencies แต่ละตัวที่พึ่งพา-testแสดงแพ็กเกจทดสอบของแต่ละแพ็กเกจ-eเอาต์พุตปกติเมื่อพบแพ็กเกจที่มีข้อผิดพลาด-findไม่แยกวิเคราะห์ความสัมพันธ์ dependencies ของแพ็กเกจเหล่านี้-exportเมื่อใช้พารามิเตอร์นี้ ตั้งค่าค่าฟิลด์Package.Exportของโครงสร้างเป็นไฟล์ที่มีข้อมูลการส่งออกที่ล่าสุดของแพ็กเกจที่ระบุ และตั้งค่าค่าฟิลด์Package.BuildIDเป็นBuildIDของแพ็กเกจ ส่วนใหญ่ใช้สำหรับการเอาต์พุตที่จัดรูปแบบ
พารามิเตอร์ข้อมูลโมดูล
-mแสดงโมดูลแทนการแสดงแพ็กเกจ-versionsแสดงข้อมูลที่ใช้ได้ทั้งหมดของโมดูล-retractedแสดงเวอร์ชันที่ถูกเพิกถอนของโมดูล
พารามิเตอร์ [packages] สามารถเป็นชื่อแพ็กเกจที่ระบุ หรือโฟลเดอร์ หรือ all แสดงว่าทุกที่ เมื่อใช้พารามิเตอร์ -m all หมายถึง dependencies ทั้งหมดที่โมดูลปัจจุบันอ้างอิง
เช่น ไฟล์ปัจจุบันมีไฟล์ main.go เพียงไฟล์เดียว และมีโค้ดเอาต์พุต "hello world" เพียงบรรทัดเดียว หลังดำเนินการ go list -deps . จะแสดงจากโปรเจกต์ปัจจุบันไปยัง fmt และแพ็กเกจ dependencies ทั้งหมดที่อ้างอิง
$ ls
go.mod go.sum main.go
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
$ go list -deps .
internal/goarch
unsafe
internal/abi
internal/unsafeheader
internal/cpu
internal/bytealg
internal/coverage/rtcov
internal/godebugs
internal/goexperiment
internal/goos
runtime/internal/atomic
runtime/internal/math
runtime/internal/sys
runtime
......
......
path
io/fs
os
fmt
golearnหรือแสดง dependencies โมดูลทั้งหมดภายใต้โปรเจกต์ปัจจุบัน
$ go list -m all
golearn
cloud.google.com/go v0.26.0
github.com/246859/containers v0.0.1
github.com/246859/river v0.1.0 => D:\WorkSpace\Code\riverdb
github.com/BurntSushi/toml v0.3.1
github.com/Jleagle/steam-go v0.0.0-20230725082712-1053b441b1f2
github.com/Jleagle/unmarshal-go v0.0.0-20210227002040-694f544f9265
github.com/KyleBanks/depth v1.2.1
github.com/Microsoft/go-winio v0.6.1
github.com/PuerkitoBio/purell v1.1.1
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578
github.com/andeya/ameda v1.5.3
github.com/andeya/goutil v1.0.1
...format
เอาต์พุตของคำสั่ง list เป็นหน่วยบรรทัด แต่ละบรรทัดที่เอาต์พุตคือแพ็กเกจ ทางการให้พารามิเตอร์ -f ที่เราสามารถกำหนดรูปแบบการเอาต์พุตบรรทัดได้ ค่าที่รับคือไวยากรณ์เทมเพลตที่กำหนดโดยแพ็กเกจเทมเพลตเอ็นจิน template/text เช่น ตัวอย่างด้านล่าง
-f "package {{ .Dir }} {{ .Name }}"แพ็กเกจที่วนซ้ำแต่ละแพ็กเกจจะถูกส่งในรูปแบบโครงสร้างต่อไปนี้ ฟิลด์ทั้งหมดในโครงสร้างนี้สามารถใช้เป็นพารามิเตอร์เทมเพลตได้
type Package struct {
Dir string // directory containing package sources
ImportPath string // import path of package in dir
ImportComment string // path in import comment on package statement
Name string // package name
Doc string // package documentation string
Target string // install path
Shlib string // the shared library that contains this package (only set when -linkshared)
Goroot bool // is this package in the Go root?
Standard bool // is this package part of the standard Go library?
Stale bool // would 'go install' do anything for this package?
StaleReason string // explanation for Stale==true
Root string // Go root or Go path dir containing this package
ConflictDir string // this directory shadows Dir in $GOPATH
BinaryOnly bool // binary-only package (no longer supported)
ForTest string // package is only for use in named test
Export string // file containing export data (when using -export)
BuildID string // build ID of the compiled package (when using -export)
Module *Module // info about package's containing module, if any (can be nil)
Match []string // command-line patterns matching this package
DepOnly bool // package is only a dependency, not explicitly listed
DefaultGODEBUG string // default GODEBUG setting, for main packages
// Source files
GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
CgoFiles []string // .go source files that import "C"
CompiledGoFiles []string // .go files presented to compiler (when using -compiled)
IgnoredGoFiles []string // .go source files ignored due to build constraints
IgnoredOtherFiles []string // non-.go source files ignored due to build constraints
CFiles []string // .c source files
CXXFiles []string // .cc, .cxx and .cpp source files
MFiles []string // .m source files
HFiles []string // .h, .hh, .hpp and .hxx source files
FFiles []string // .f, .F, .for and .f90 Fortran source files
SFiles []string // .s source files
SwigFiles []string // .swig files
SwigCXXFiles []string // .swigcxx files
SysoFiles []string // .syso object files to add to archive
TestGoFiles []string // _test.go files in package
XTestGoFiles []string // _test.go files outside package
// Embedded files
EmbedPatterns []string // //go:embed patterns
EmbedFiles []string // files matched by EmbedPatterns
TestEmbedPatterns []string // //go:embed patterns in TestGoFiles
TestEmbedFiles []string // files matched by TestEmbedPatterns
XTestEmbedPatterns []string // //go:embed patterns in XTestGoFiles
XTestEmbedFiles []string // files matched by XTestEmbedPatterns
// Cgo directives
CgoCFLAGS []string // cgo: flags for C compiler
CgoCPPFLAGS []string // cgo: flags for C preprocessor
CgoCXXFLAGS []string // cgo: flags for C++ compiler
CgoFFLAGS []string // cgo: flags for Fortran compiler
CgoLDFLAGS []string // cgo: flags for linker
CgoPkgConfig []string // cgo: pkg-config names
// Dependency information
Imports []string // import paths used by this package
ImportMap map[string]string // map from source import to ImportPath (identity entries omitted)
Deps []string // all (recursively) imported dependencies
TestImports []string // imports from TestGoFiles
XTestImports []string // imports from XTestGoFiles
// Error information
Incomplete bool // this package or a dependency has an error
Error *PackageError // error loading package
DepsErrors []*PackageError // errors loading dependencies
}
type PackageError struct {
ImportStack []string // shortest path from package named on command line to this one
Pos string // position of error (if present, file:line:col)
Err string // the error itself
}หากวนซ้ำโมดูล จะส่งในรูปแบบโครงสร้างต่อไปนี้ ฟิลด์ทั้งหมดของมันสามารถใช้เป็นพารามิเตอร์เทมเพลตได้เช่นกัน
type Module struct {
Path string // module path
Query string // version query corresponding to this version
Version string // module version
Versions []string // available module versions
Replace *Module // replaced by this module
Time *time.Time // time version was created
Update *Module // available update (with -u)
Main bool // is this the main module?
Indirect bool // module is only indirectly needed by main module
Dir string // directory holding local copy of files, if any
GoMod string // path to go.mod file describing module, if any
GoVersion string // go version used in module
Retracted []string // retraction information, if any (with -retracted or -u)
Deprecated string // deprecation message, if any (with -u)
Error *ModuleError // error loading module
Origin any // provenance of module
Reuse bool // reuse of old module info is safe
}
type ModuleError struct {
Err string // the error itself
}ดูแพ็กเกจทั้งหมด
$ go list -f "package {{.Dir}} {{.Name}}" ./...
package /golearn main
package /golearn/app cmd
package /golearn/cmd cmd
package /golearn/docs docs
package /golearn/tool tool
package /golearn/tool_test toolดูโมดูล
$ go list -m -f "mod {{.Path}} {{.Version}} {{.GoVersion}} {{.GoMod}}"
mod golearn 1.21.3 /golearn/go.modmod
go mod เป็นคำสั่งสำหรับจัดการโมดูล go โดยเฉพาะ
$ go mod help
Go mod provides access to operations on modules.
Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.
Usage:
go mod <command> [arguments]
The commands are:
download download modules to local cache
edit edit go.mod from tools or scripts
graph print module requirement graph
init initialize new module in current directory
tidy add missing and remove unused modules
vendor make vendored copy of dependencies
verify verify dependencies have expected content
why explain why packages or modules are needed
Use "go help mod <command>" for more information about a command.มีคำสั่งย่อยดังนี้
downloadดาวน์โหลด dependencies ทั้งหมดที่ระบุในไฟล์go.modไปยังแคชท้องถิ่นeditแก้ไขไฟล์go.modอินเทอร์เฟซบรรทัดคำสั่งที่ให้ไว้ส่วนใหญ่สำหรับเครื่องมือหรือสคริปต์อื่นเรียกใช้initเริ่มต้นโปรเจกต์ gomod ในไดเรกทอรีปัจจุบันtidyดาวน์โหลด dependencies ที่ขาดหายไป ลบ dependencies ที่ไม่ใช้graphแสดงกราฟ dependenciesverifyตรวจสอบ dependencies ท้องถิ่นwhyอธิบายว่าทำไมต้องพึ่งพาโมดูลเหล่านี้vendorส่งออก dependencies ของโปรเจกต์ไปยังไดเรกทอรี vendor
init
$ go help mod init
usage: go mod init [module-path]คำสั่ง init ใช้สำหรับเริ่มต้นโปรเจกต์ gomod พารามิเตอร์เดียวคือพาธโมดูล ในอนาคตหากผู้อื่นต้องการดาวน์โหลด dependencies ของคุณจะต้องใช้พาธโมดูลนี้เป็นพื้นฐาน กฎการตั้งชื่อโดยทั่วไปคือ
domain_name/user_name/repo_nameเช่น โดยทั่วไปแล้วทุกคนมักจะวางโปรเจกต์บน github ดังนั้นอาจเป็น
github.com/jack/gotourไม่แนะนำให้ใช้สัญลักษณ์พิเศษเป็นพาธโมดูล ดูตัวอย่างการใช้งาน
$ mkdir gotour
$ cd gotour
$ go mod init "github.com/jack/gotour"
go: creating new go.mod: module github.com/jack/gotourtidy
$ go help mod tidy
usage: go mod tidy [-e] [-v] [-x] [-go=version] [-compat=version]คำสั่ง tidy จะล้างรายการ dependencies ที่ไม่ใช้ใน go.mod ซึ่งก็คือรายการ dependencies ที่ไม่ถูกอ้างอิง และจะดาวน์โหลด dependencies ที่ถูกอ้างอิงแต่ไม่มีอยู่ รองรับพารามิเตอร์ต่อไปนี้
-vแสดง dependencies โมดูลที่ถูกลบ-eละเว้นข้อผิดพลาดหากเกิดขึ้นในระหว่างกระบวนการและดำเนินการต่อ-xแสดงกระบวนการดำเนินการ-go=versionอัปเดตเวอร์ชัน go ในไฟล์go.mod-compact=versionรักษา checksum เพิ่มเติมที่จำเป็นจากเวอร์ชัน Go หลักที่ระบุเพื่อโหลดกราฟโมดูลให้สำเร็จ และหากคำสั่งgoของเวอร์ชันนี้โหลดแพ็กเกจที่นำเข้าใด ๆ จากเวอร์ชันโมดูลที่ต่างกัน จะทำให้ tidy เกิดข้อผิดพลาด โดยทั่วไปแล้วพารามิเตอร์นี้ไม่ค่อยได้ใช้ มักจะเกิดข้อผิดพลาดเมื่อมีการเปลี่ยนแปลงเวอร์ชัน สามารถดูคำตอบนี้ใน stackoverflow go modules - go mod tidy error message: "but go 1.16 would select" - Stack Overflow
ดูตัวอย่างการใช้งาน
$ go mod tidy -v
unused github.com/246859/containers
unused github.com/246859/river
unused github.com/Jleagle/steam-go
unused github.com/Jleagle/unmarshal-go
unused github.com/KyleBanks/depth
unused github.com/Microsoft/go-winio
unused github.com/PuerkitoBio/purell
unused github.com/PuerkitoBio/urlesc
unused github.com/andeya/ameda
unused github.com/andeya/goutil
unused github.com/asaskevich/govalidator
unused github.com/buger/jsonparser
unused github.com/bwmarrin/snowflake
unused github.com/bytedance/go-tagexpr/v2
unused github.com/bytedance/sonic
unused github.com/cespare/xxhash/v2
unused github.com/chenzhuoyu/base64x
......download
$ go help mod download
usage: go mod download [-x] [-json] [-reuse=old.json] [modules]แม้ว่าชื่อของคำสั่ง download จะแปลว่าการดาวน์โหลด แต่เพียงดาวน์โหลด dependencies ไปยังแคช dependencies ท้องถิ่นเท่านั้น ไม่แก้ไขไฟล์ go.mod ฟังก์ชันของมันคือพรีดาวน์โหลด dependencies ไปยังแคชไฟล์ท้องถิ่น หากคุณต้องการดาวน์โหลด dependencies ใด dependencies หนึ่ง แนะนำให้ใช้ go get หรือ go mod tidy
ต่อไปนี้เป็นตัวอย่างการใช้งานบางตัว
$ go mod download -x gorm.io/gorm
# get https://goproxy.cn/gorm.io/gorm/@v/list
# get https://goproxy.cn/gorm.io/gorm/@v/list: 200 OK (0.084s)หากไม่มีพารามิเตอร์ใด ๆ จะดาวน์โหลด dependencies ทั้งหมดที่มีอยู่ในไฟล์ go.mod แต่ไม่มีอยู่ในแคช dependencies ท้องถิ่น หากไม่มีอะไรให้ดาวน์โหลดจะแสดง
go: no module dependencies to downloadedit
$ go help mod edit
usage: go mod edit [editing flags] [-fmt|-print|-json] [go.mod]edit เป็นอินเทอร์เฟซบรรทัดคำสั่งสำหรับแก้ไขไฟล์ go.mod มัก提供给โปรแกรมอื่นใช้ IDE ของบรรณาธิการบางตัวเพื่อรองรับ gomod จะใช้คำสั่งเหล่านี้ รองรับพารามิเตอร์ต่อไปนี้
-moduleแก้ไขพาธโมดูล-go=versionแก้ไขเวอร์ชัน go ที่คาดหวัง-require=path@versionเพิ่มรายการ dependencies-droprequire=path@versionลบรายการ dependencies-exclude=path@versionเพิ่มรายการยกเว้น dependencies-dropexclude=path@versionลบรายการยกเว้น dependencies-replace=old@version=new@versionเพิ่มรายการแทนที่ dependencies-dropreplace=old@versionลบรายการแทนที่ dependencies-retract=versionเพิ่มรายการเพิกถอนเวอร์ชัน-dropretract=versionลบรายการเพิกถอนเวอร์ชัน
มีพารามิเตอร์อื่น ๆ สำหรับแสดง
-printแสดงเนื้อหาไฟล์-jsonแสดงในรูปแบบ json
เช่น ตัวอย่างด้านล่างนี้
$ go mod edit -print
module golearn
go 1.21.3
require (
github.com/dstgo/task v1.2.0
github.com/spf13/cast v1.5.1
github.com/swaggo/swag v1.16.2
golang.org/x/net v0.19.0
gorm.io/gorm v1.25.5
)graph
$ go help mod graph
usage: go mod graph [-go=version] [-x]คำสั่ง graph จะแสดงกราฟ dependencies ภายใต้โปรเจกต์ปัจจุบัน การอ่านได้แย่มาก และส่วนใหญ่แล้วไม่ใช่สำหรับมนุษย์อ่าน ผลลัพธ์มักจะถูกประมวลผลแล้วแสดงในรูปแบบภาพ แต่ละบรรทัดคือ dependencies หนึ่งรายการ รูปแบบดังนี้
引用方 被引用方เช่น
golearn go@1.21.3ยังรองรับพารามิเตอร์สองตัว
-go=versionใช้เวอร์ชัน go ที่กำหนดโหลดกราฟ dependencies ค่าของมันต้องไม่น้อยกว่าเวอร์ชันในไฟล์go.mod-xแสดงคำสั่งที่ดำเนินการในระหว่างกระบวนการ
ดูตัวอย่างการใช้งานง่าย ๆ
$ go mod graph
golearn github.com/246859/containers@v0.0.1
golearn github.com/246859/river@v0.1.0
golearn github.com/Jleagle/steam-go@v0.0.0-20230725082712-1053b441b1f2
golearn github.com/Jleagle/unmarshal-go@v0.0.0-20210227002040-694f544f9265
golearn github.com/KyleBanks/depth@v1.2.1
golearn github.com/Microsoft/go-winio@v0.6.1
golearn github.com/PuerkitoBio/purell@v1.1.1
golearn github.com/PuerkitoBio/urlesc@v0.0.0-20170810143723-de5bf2ad4578
golearn github.com/andeya/ameda@v1.5.3
golearn github.com/andeya/goutil@v1.0.1
golearn github.com/asaskevich/govalidator@v0.0.0-20230301143203-a9d515a09cc2
golearn github.com/buger/jsonparser@v1.1.1
golearn github.com/bwmarrin/snowflake@v0.3.0
golearn github.com/bytedance/go-tagexpr/v2@v2.9.11
......vendor
$ go help mod vendor
usage: go mod vendor [-e] [-v] [-o outdir]vendor เป็นแผนการแทนที่ gopath ก่อนที่ gomod จะถูกเปิดตัว ภายใต้แต่ละโปรเจกต์ go จะมีไดเรกทอรี vendor หนึ่งไดเรกทอรี เก็บ dependencies ของแต่ละโปรเจกต์แยกกันในรูปแบบ domain/user/project เช่นเดียวกับ node_module ที่อ้วนของ nodeJs ข้าง ๆ dependencies ของแต่ละโปรเจกต์แยกกัน วิธีจัดการ dependencies แบบนี้现在看来确实很โง่ แต่ในเวลานั้น确实ไม่มีแผนที่ดีกว่า เหตุผลที่ยังคงรักษา vendor ไว้เพราะ go ยึดมั่นในสัญญาความเข้ากันได้แบบลงล่าง โปรเจกต์เก่าบางโปรเจกต์รวมถึงซอร์สโค้ดของ go อาจยังใช้ vendor
กลับเข้าเรื่อง vendor เป็นคำสั่งย่อยของ go mod สามารถส่งออก dependencies ส่วนกลางที่โมดูลปัจจุบันอ้างอิงไปยังไดเรกทอรี vendor
$ go mod vendor -h
usage: go mod vendor [-e] [-v] [-o outdir]
Run 'go help mod vendor' for details.มีพารามิเตอร์ดังนี้
-oระบุพาธโฟลเดอร์เอาต์พุต-vแสดง dependencies แต่ละตัว-eไม่ออกเมื่อเกิดข้อผิดพลาดยังคงดำเนินการต่อ
ดูตัวอย่าง ใช้ go list -m all ดู dependencies ที่โปรเจกต์ปัจจุบันอ้างอิงก่อน
$ go list -m all
github.com/dstgo/task
github.com/davecgh/go-spew v1.1.1
github.com/pkg/errors v0.9.1
github.com/pmezard/go-difflib v1.0.0
github.com/stretchr/objx v0.5.0
github.com/stretchr/testify v1.8.4
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
gopkg.in/yaml.v3 v3.0.1ส่งออกไปยังไดเรกทอรี vendor ปัจจุบัน
$ go mod vendor -v -e -o vendor
# github.com/davecgh/go-spew v1.1.1
## explicit
github.com/davecgh/go-spew/spew
# github.com/pkg/errors v0.9.1
## explicit
github.com/pkg/errors
# github.com/pmezard/go-difflib v1.0.0
## explicit
github.com/pmezard/go-difflib/difflib
# github.com/stretchr/testify v1.8.4
## explicit; go 1.20
github.com/stretchr/testify/assert
# gopkg.in/yaml.v3 v3.0.1
## explicit
gopkg.in/yaml.v3โครงสร้างไดเรกทอรีหลังส่งออกมีดังนี้
└─vendor
├─github.com
│ ├─davecgh
│ │ └─go-spew
│ │ └─spew
│ ├─pkg
│ │ └─errors
│ ├─pmezard
│ │ └─go-difflib
│ │ └─difflib
│ └─stretchr
│ └─testify
│ └─assert
└─gopkg.in
| └─yaml.v3
|
|--modules.txtในนั้น modules.txt เป็นไฟล์ที่อธิบายรายการ dependencies ทั้งหมด เหมือนกับ go.mod ในปัจจุบัน
verify
$ go help mod verify
usage: go mod verifyคำสั่งนี้จะตรวจสอบว่า dependencies ของโปรเจกต์ถูกแก้ไขหรือไม่หลังจากดาวน์โหลดไปยังท้องถิ่น เช่น หากไม่มีปัญหาจะแสดง all modules verified
$ go mod verify
all modules verifiedมิฉะนั้นจะรายงานว่ามีการเปลี่ยนแปลงที่ไหน และสิ้นสุดคำสั่งด้วยสถานะผิดปกติ เช่น
$ go mod verify
gorm.io/gorm v1.25.5: dir has been modified (/go/mod/libs/gorm.io/gorm@v1.25.5)why
$ go help mod why
usage: go mod why [-m] [-vendor] packages...อธิบายว่าทำไมแพ็กเกจนี้ถึงถูกพึ่งพา จริง ๆ แล้วคือการแสดงกราฟ dependencies เกี่ยวกับมัน เช่น
$ go mod why gorm.io/gorm
# gorm.io/gorm
golearn
gorm.io/gormโดยค่าเริ่มต้นจะแยกวิเคราะห์การนำเข้าจาก main เท่านั้น เพิ่มพารามิเตอร์ -m สามารถวิเคราะห์สถานการณ์การนำเข้าของแต่ละแพ็กเกจ
work
คำสั่ง work เป็นเครื่องมือพัฒนาท้องถิ่นสำหรับจัดการหลายโมดูลของ go
$ go work help
Work provides access to operations on workspaces.
Note that support for workspaces is built into many other commands, not
just 'go work'.
The commands are:
edit edit go.work from tools or scripts
init initialize workspace file
sync sync workspace build list to modules
use add modules to workspace file
vendor make vendored copy of dependencies
Use "go help work <command>" for more information about a command.init
คำสั่งย่อย init ใช้สำหรับเริ่มต้น workspace หนึ่งคำสั่งนี้จะสร้างไฟล์ชื่อ go.work
$ go work init -h
usage: go work init [moddirs]
Run 'go help work init' for details.รับพารามิเตอร์ [moddirs] ระบุว่าโมดูลใดบ้างที่จะรวมในการจัดการ เช่น
$ go work init ./service ./apiuse
คำสั่งย่อย use ใช้สำหรับเพิ่มไดเรกทอรีโมดูลที่รวมในการจัดการลงใน go.work
$ go help work use
usage: go work use [-r] [moddirs]
Use provides a command-line interface for adding
directories, optionally recursively, to a go.work file.รับ [moddirs] เป็นพารามิเตอร์ และมี -r แสดงว่าค้นหาโมดูลแบบเรียกซ้ำภายใต้พาธ [moddirs] เช่น
$ go work use -r ./oss-api ./multi_modulesedit
ฟังก์ชันของคำสั่งย่อย edit เหมือนกับ go mod edit ทั้งคู่留给อินเทอร์เฟซบรรทัดคำสั่งสำหรับเครื่องมือและสคริปต์อื่นดำเนินการ
$ go help work edit
usage: go work edit [editing flags] [go.work]
Edit provides a command-line interface for editing go.work,
for use primarily by tools or scripts. It only reads go.work;
it does not look up information about the modules involved.
If no file is specified, Edit looks for a go.work file in the current
directory and its parent directoriesพารามิเตอร์มีดังนี้
-fmtจัดรูปแบบไฟล์go.work-use,-dropuseเพิ่มและลบพาธโมดูล-replace=old[@v]=new[@v],-dropreplace=old[@v]=new[@v]ใช้สำหรับเพิ่มและลบโมดูลที่จะแทนที่-go,-toolchain=nameระบุเวอร์ชัน go และระบุเครื่องมือที่จะใช้-printพิมพ์การแก้ไขสุดท้าย ไม่เขียนกลับไฟล์-jsonแสดงในรูปแบบjsonไม่สามารถใช้กับ-printพร้อมกันได้ โครงสร้างประเภทมีดังนี้gotype GoWork struct { Go string Toolchain string Use []Use Replace []Replace } type Use struct { DiskPath string ModulePath string } type Replace struct { Old Module New Module } type Module struct { Path string Version string }
ตัวอย่างการใช้งานบางตัว แสดงผลลัพธ์ที่จัดรูปแบบ
$ go work edit -fmt -print
go 1.22.0
use (
./ab/cd
./auth
./user
)แสดงผลลัพธ์ json
$ go work edit -fmt -json
{
"Go": "1.22.0",
"Use": [
{
"DiskPath": "./ab/cd"
},
{
"DiskPath": "./auth"
},
{
"DiskPath": "./user"
}
],
"Replace": null
}sync
คำสั่งย่อย sync ใช้สำหรับซิงค์รายการโมดูลใน go.work กลับไปยังแต่ละโมดูลใน workspace
$ go help work sync
usage: go work sync
Sync syncs the workspace's build list back to the
workspace's modulesกระบวนการนี้เกิดขึ้นหลักหลังจากการพัฒนาท้องถิ่นเสร็จสิ้น โมดูลแต่ละโมดูลเสร็จสิ้นการเผยแพร่แล้ว ใช้ sync ในเวลานี้ จะอัปเดต dependencies ใน go.mod ของโมดูลทั้งหมดใน worksapce ตามความสัมพันธ์ dependencies ของโมดูลแต่ละโมดูล จึงไม่จำเป็นต้องอัปเดตด้วยตนเอง
vendor
คำสั่ง vendor จะทำสำเนาไลบรารี dependencies ทั้งหมดของโมดูลใน workspace ไปยังไดเรกทอรี vendor
$ go work help vendor
usage: go work vendor [-e] [-v] [-o outdir]ฟังก์ชันเหมือนกับ go mod vendor ไม่ขออธิบายเพิ่มเติม
vet
คำสั่ง vet เป็นเครื่องมือตรวจสอบข้อผิดพลาดแบบคงที่สำหรับซอร์สโค้ดภาษา go เหมือนกับเครื่องมือ lint ของภาษาอื่น เช่น Eslint
$ go vet -h
usage: go vet [build flags] [-vettool prog] [vet flags] [packages]
Run 'go help vet' for details.
Run 'go tool vet help' for a full list of flags and analyzers.
Run 'go tool vet -help' for an overview.ดูตัวอย่างง่าย ๆ ก่อน มีซอร์สโค้ดดังนี้
$ cat main.go
package main
import "fmt"
func main(){
fmt.Println("hello world!"
}ดำเนินการ go vet ในไดเรกทอรีเดียวกันโดยไม่มีพารามิเตอร์ใด ๆ
$ go vet
vet: ./main.go:6:28: missing ',' before newline in argument list (and 1 more errors)vet จะรายงานว่าไฟล์ใด บรรทัดใด เกิดปัญหาอะไร รองรับแฟลกการสร้างเป็นพารามิเตอร์ เช่น -n และ -x รองรับแพ็กเกจ โฟลเดอร์ ชื่อไฟล์ เป็นพารามิเตอร์
$ go vet .
$ go vet main.go
$ go vet ./cmd
$ go vet runtimeดูพารามิเตอร์และคำอธิบายที่ละเอียดมากขึ้นผ่านคำสั่งต่อไปนี้
$ go tool vet help
vet is a tool for static analysis of Go programs.
vet examines Go source code and reports suspicious constructs,
such as Printf calls whose arguments do not align with the format
string. It uses heuristics that do not guarantee all reports are
genuine problems, but it can find errors not caught by the compilers.
Registered analyzers:
asmdecl report mismatches between assembly files and Go declarations
assign check for useless assignments
atomic check for common mistakes using the sync/atomic package
bools check for common mistakes involving boolean operators
buildtag check //go:build and // +build directives
......คำสั่ง go tool vet ไม่สามารถใช้ตรวจสอบโค้ดได้โดยตรง ควรใช้ go vet พารามิเตอร์ [vet flag] ในพารามิเตอร์ของ go vet รองรับตั้งค่าตัววิเคราะห์โค้ด ค่าที่ใช้ได้มีดังนี้
asmdecl ตรวจสอบว่าไฟล์ assembly ไม่ตรงกับการประกาศ go
assign ตรวจสอบว่ามีตัวแปรที่ไม่ได้ใช้
atomic ตรวจสอบว่าใช้ sync/atomic ทำลายความเป็นอะตอมหรือไม่
bools ตรวจสอบว่าใช้ตัวดำเนินการตรรกะผิดพลาดหรือไม่
buildtag ตรวจสอบ build tag
cgocall ตรวจสอบพฤติกรรมที่ละเมิดกฎการส่งพอยน์เตอร์ของ cgao
composites ตรวจสอบโครงสร้างคอมโพสิตที่ไม่ได้เริ่มต้น เช่น map, chan
copylocks ตรวจสอบว่าเกิดการคัดลอกค่าของล็อกหรือไม่
directive ตรวจสอบคำสั่งเครื่องมือ go
errorsas ตรวจสอบว่าส่งประเภทที่ไม่ใช่พอยน์เตอร์หรือประเภทที่ไม่ใช่ error ไปยัง errors.As หรือไม่
framepointer ตรวจสอบว่าโค้ด assembly ที่เพิ่มประสิทธิภาพการคอมไพล์แล้วล้างเฟรมพอยน์เตอร์ก่อนบันทึกหรือไม่
httpresponse ตรวจสอบว่าใช้ httpresponse ผิดพลาดหรือไม่
ifaceassert ตรวจสอบการยืนยันประเภทจากอินเทอร์เฟซไปยังอินเทอร์เฟซ
loopclosure ปัญหาการอ้างอิงตัวแปรลูป
lostcancel context.WithCancel ไม่ได้ใช้ฟังก์ชัน cancel
nilfunc ตรวจสอบว่าการเปรียบเทียบระหว่างฟังก์ชันและ nil ไม่มีประโยชน์หรือไม่
printf ตรวจสอบว่าพารามิเตอร์การจัดรูปแบบของ printf ถูกต้องหรือไม่
shift ตรวจสอบว่ามีการเลื่อนที่เท่ากับหรือเกินความกว้างของจำนวนเต็มหรือไม่
sigchanyzer ตรวจสอบ chan os.Signal ที่ไม่มีบัฟเฟอร์
slog ตรวจสอบการเรียกบันทึกที่มีโครงสร้างไม่ถูกต้อง
stdmethods ตรวจสอบว่าลายเซ็นของเมธอดอินเทอร์เฟซที่รู้จักถูกต้องหรือไม่
stringintconv ตรวจสอบการแปลงจำนวนเต็มสตริง
structtag ตรวจสอบว่า tag ของโครงสร้างถูกต้องหรือไม่
testinggoroutine ตรวจสอบว่าใช้协程ในการเรียก testing.Fatal ในการทดสอบหรือไม่
tests ตรวจสอบข้อผิดพลาดทั่วไปในการทดสอบและตัวอย่าง
timeformat ตรวจสอบว่ารูปแบบเวลาที่เรียกใช้ (time.Time).Format หรือ time.Parse ถูกต้องหรือไม่
unmarshal ส่งประเภทที่ไม่ใช่พอยน์เตอร์หรืออินเทอร์เฟซไปยัง unmarshal
unreachable ตรวจสอบโค้ดที่ไปไม่ถึง
unsafeptr ตรวจสอบการแปลง uintptr เป็น unsafe.Pointer ไม่ถูกต้อง
unusedresult ตรวจสอบค่าส่งกลับของฟังก์ชันที่ไม่ได้ใช้ล้วนเป็นตัววิเคราะห์ที่วิเคราะห์จุดใดจุดหนึ่ง เช่น ตัววิเคราะห์ timeformat ตรวจสอบว่าการเรียก time.Format ตรงตามไวยากรณ์ที่ถูกต้องหรือไม่ โดยค่าเริ่มต้นตัววิเคราะห์ทั้งหมดข้างต้นจะเปิดใช้งาน เปิดใช้งานแยกต่างหากสามารถใช้รูปแบบดังนี้
$ go vet -timeformat main.goปิดใช้งานแยกต่างหาก
$ go vet -timeformat=false main.goซอร์สโค้ดของตัววิเคราะห์เหล่านี้อยู่ที่ cmd/vendor/golang.org/x/tools/go/analysis/passes ตัววิเคราะห์แต่ละตัวเป็นหลุมที่ภาษา go มักจะตก ดังนั้นจึงแนะนำให้ใช้คำสั่ง vet ตรวจสอบโค้ดของคุณ นอกจากเหล่านี้แล้ว ยังรองรับแฟลกพารามิเตอร์อื่น ๆ
-Vพิมพ์เวอร์ชันแล้วออกเท่านั้น-jsonแสดงในรูปแบบ json-c=nแสดงบรรทัดที่มีความขัดแย้งในบริบทที่ระบุจำนวน (ดูเหมือนจะไม่มีผลใด ๆ)
ยังมีตัววิเคราะห์ภายนอก เช่น shadows รับผิดชอบตรวจสอบปัญหาการซ่อนตัวแปรของการตั้งชื่อตัวแปรแบบสั้น เนื่องจากเป็นภายนอกจึงต้องใช้ go install ในการดาวน์โหลด
$ go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latestรูปแบบการใช้งานดังนี้
$ go vet -vettool=$(which shadow)test
$ go test -h
usage: go test [build/test flags] [packages] [build/test flags & test binary flags]
Run 'go help test' and 'go help testflag' for details.คำสั่ง test เป็นคำสั่งที่ให้ฟังก์ชันการทดสอบในเครื่องมือ go ฟังก์ชันนี้สำคัญมาก สำหรับซอฟต์แวร์แล้ว การทดสอบที่สมบูรณ์เป็นสิ่งที่ขาดไม่ได้ ที่นี่เพียงแนะนำวิธีใช้คำสั่ง test อย่างง่าย ๆ หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการทดสอบ ไปที่ การทดสอบ
นอกจากพารามิเตอร์การคอมไพล์ของคำสั่ง build แล้ว test ยังรองรับพารามิเตอร์ต่อไปนี้
-argsพารามิเตอร์ entry ของโปรแกรม-cคอมไพล์ไฟล์ไบนารีทดสอบของแพ็กเกจปัจจุบันไปยังไดเรกทอรีปัจจุบันแต่ไม่ดำเนินการ ตั้งชื่อในรูปแบบpkg.test-execดำเนินการคำสั่งอื่น ๆ ก่อนเริ่มการทดสอบ-jsonสไตล์การเอาต์พุตของการทดสอบเป็น json-oระบุพาธชื่อไฟล์ของไฟล์ไบนารีทดสอบ
ยังรองรับ testflag จำนวนมาก ใช้คำสั่ง help ดู testflag ทั้งหมด
$ go help testflag
`go test` 命令既接受作用于 `go test` 本身的标志,
也接受作用于生成的测试二进制文件的标志。
`go test` 命令识别以下标志,并用于控制任何测试的执行:
-bench regexp
-benchtime t
-count n
......แนะนำตัวที่ใช้บ่อย
-vแสดงผลการทดสอบของแต่ละเคส-timeout durationเวลา超时ของการดำเนินการทดสอบ-skip regexpข้ามเคสการทดสอบที่ระบุ-shortให้เคสการทดสอบที่ใช้เวลานานมากลดเวลาการรัน-shuffleสลับลำดับการดำเนินการของเคสการทดสอบทั้งหมด-run regexpรันเคสการทดสอบที่ระบุ-list regexpแสดงรายการเคสการทดสอบแต่ละเคส-cpu 1,2,4ระบุจำนวน cpu-count nระบุให้แต่ละเคสการทดสอบดำเนินการกี่ครั้ง
วิธีการใช้ง่ายที่สุดคือ ไม่มีพารามิเตอร์ใด ๆ จะดำเนินการเคสการทดสอบทั้งหมดภายใต้แพ็กเกจปัจจุบัน และแสดงผลลัพธ์
$ ls *_test.go
hello_test.go
$ go test
PASS
ok golearn 0.522sระบุไฟล์ทดสอบใดไฟล์ทดสอบหนึ่ง
$ go test hello_test.go
ok command-line-arguments 0.041sเพิ่มพารามิเตอร์ -v สามารถดูเอาต์พุตที่ละเอียดมากขึ้น มันค่อนข้างใช้บ่อย
$ go test -v hello_test.go
=== RUN TestHello
hello_test.go:6: hello world!
--- PASS: TestHello (0.00s)
PASS
ok command-line-arguments 0.041sระบุเคสการทดสอบใดเคสการทดสอบหนึ่ง
$ go test -v -run TestHello
=== RUN TestHello
hello_test.go:6: hello world!
--- PASS: TestHello (0.00s)
PASS
ok golearn 0.028sในการทดสอบ คำสั่ง test มีสองโหมด ก่อนอื่นมาพูดถึงโหมดโฟลเดอร์แรก เมื่อดำเนินการคำสั่ง test โดยไม่มีพารามิเตอร์ package จะดำเนินการทดสอบในโหมดโฟลเดอร์ เช่น คำสั่งต่อไปนี้
$ go test
$ go test -vในโหมดนี้ ปิดใช้งานแคชการทดสอบ อีกโหมดหนึ่งคือโหมดรายการ เมื่อพารามิเตอร์ package ไม่ว่าง จะดำเนินการทดสอบในโหมดรายการ ความแตกต่างระหว่างมันกับโหมดก่อนหน้าคือเปิดใช้งานแคชการทดสอบหรือไม่ เช่น คำสั่งต่อไปนี้
$ go test -v .
$ go test -v ./...
$ go test .
$ go test -v net/httpในโหมดรายการ go จะคอมไพล์ไฟล์ทดสอบของแต่ละแพ็กเกจภายใต้แพ็กเกจที่ระบุเป็นไฟล์ไบนารีและดำเนินการ เพื่อหลีกเลี่ยงการรันการทดสอบซ้ำ go จะแคชผลลัพธ์โดยค่าเริ่มต้น การรันครั้งที่สองจะไม่คอมไพล์ใหม่ เมื่อใช้พารามิเตอร์ต่อไปนี้จะเปิดใช้งานแคชโดยค่าเริ่มต้น
-benchtime-cpu-list-parallel-runshort-timeout-failfast-v
ใช้พารามิเตอร์อื่นนอกเหนือจากพารามิเตอร์เหล่านี้สามารถปิดแคชได้ วิธีการที่ทางการแนะนำคือใช้ -count=1 เพื่อปิดแคช เช่น
$ go test -v -count=1 ./...คำสั่ง
แตกต่างจากคำสั่ง คำสั่งของ go มีอยู่ในไฟล์ซอร์สในรูปแบบฮาร์ดโค้ด มีชื่ออีกชื่อหนึ่งที่เป็นศัพท์เทคนิคมากขึ้น คือ编译指示 (progma directives)
คอมไพเลอร์และลิงก์เกอร์จะเปลี่ยนพฤติกรรมของตัวเองเนื่องจากพวกมันเพื่อบรรลุผลการควบคุมการคอมไพล์ คล้ายกับมาโครในภาษา c แน่นอนว่าไม่ใช่คำสั่งทั้งหมดที่ใช้สำหรับการ影響การคอมไพล์ บางคำสั่งใช้สำหรับพฤติกรรมฟังก์ชันอื่น ๆ เช่น คำสั่ง generate มักใช้สำหรับฟังก์ชันการสร้างโค้ด คำสั่งเหล่านี้มักมีอยู่ในรูปแบบความคิดเห็น และขึ้นต้นด้วย //go: ไม่มีช่องว่างระหว่างกลาง เช่น คำสั่ง //go:generate ประเภทคำสั่งทั้งหมดแบ่งเป็นสองประเภท
- คำสั่งฟังก์ชัน นี่คือคำสั่งฟังก์ชันที่ go ให้สามารถใช้ได้อย่างอิสระ เช่น
generate,embed,build - คำสั่งคอมไพเลอร์ คำสั่งประเภทนี้ต้องใช้ด้วยความระมัดระวัง การใช้โดยไม่ระวังอาจนำไปสู่ผลลัพธ์ที่ไม่สามารถคาดเดาได้
ยกเว้นคำสั่งฟังก์ชัน คำสั่งส่วนใหญ่สามารถ作用于ฟังก์ชัน签名เท่านั้น สำหรับคำสั่งคอมไพเลอร์สามารถดำเนินการคำสั่ง go doc compile เพื่อดูคำสั่ง สำหรับคำสั่งทั้งหมด สามารถค้นหาข้อมูลเกี่ยวกับพวกมันได้ที่ cmd/compile/internal/ir/node.go: 440
generate
$ go help generate
usage: go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]คำสั่ง generate ตามชื่อหมายถึงเกี่ยวข้องกับการสร้าง โดยปกติฟังก์ชันของมันใช้สำหรับดำเนินการคำสั่งที่จะสร้างโค้ดและอัปเดตซอร์สโค้ด แต่จริง ๆ แล้วสามารถดำเนินการคำสั่งใด ๆ ก็ได้ และคำสั่ง generate แตกต่างจากคำสั่งอื่น มีคำสั่งเฉพาะสำหรับดำเนินการคำสั่ง generate ทั้งหมดที่อยู่ในไฟล์ซอร์ส สามารถใช้ชื่อไฟล์หรือชื่อแพ็กเกจเป็นพารามิเตอร์เข้าเพื่อระบุว่าดำเนินการคำสั่ง generate ของไฟล์ใด ด้านล่างเป็นพารามิเตอร์อื่นของมัน
-run=regexดำเนินการคำสั่ง generate ที่ระบุ-skip=regexข้ามคำสั่ง generate ที่ระบุ-nพิมพ์คำสั่งที่จะดำเนินการ-xพิมพ์คำสั่งที่ดำเนินการในระหว่างกระบวนการ-vแสดงไฟล์ที่ประมวลผล
นอกจากนี้ ในคำสั่งที่ดำเนินการในคำสั่ง generate ยังรองรับพารามิเตอร์ในตัวต่อไปนี้
$GOARCHสถาปัตยกรรม cpu$GOOSระบบปฏิบัติการ$GOFILEชื่อไฟล์$GOLINEหมายเลขบรรทัด$GOPACKAGEชื่อแพ็กเกจ$GOROOTgo root$DOLLARสัญลักษณ์ดอลลาร์$PATHตัวแปรสภาพแวดล้อม path
ดูตัวอย่าง ไม่มีโค้ดใด ๆ มีเพียงความคิดเห็นหนึ่งบรรทัด
package main
//go:generate echo "hello world!"ดำเนินการคำสั่ง
$ go generate .
hello world!ตัวอย่างนี้คือดำเนินการคำสั่ง go
package main
//go:generate go versionดำเนินการคำสั่ง
$ go generate .
go version go1.21.3 windows/amd64คำสั่ง generate สามารถใช้สำหรับดำเนินการคำสั่งใด ๆ เช่น swagger สร้างเอกสาร API หรือ Wire สร้างโค้ด IOC อย่างไรก็ตาม คำสั่งนี้ไม่เหมาะสำหรับดำเนินการคำสั่งที่ซับซ้อนมาก มันเหมาะสำหรับดำเนินการคำสั่งสั้น ๆ หากมีความต้องการที่ซับซ้อนสามารถใช้สคริปต์หรือ makefile แทน
embed
คำสั่ง embed เป็นคำสั่งใหม่ที่เพิ่มใน 1.16 ฟังก์ชันของมันคือสามารถแพ็กไฟล์สถิตร่วมกับไฟล์ไบนารีได้ เช่น เทมเพลต HTML เป็นต้น รูปแบบของมันมีดังนี้
//go:embed patternpattern สามารถเป็นนิพจน์ glob หรือโฟลเดอร์หรือไฟล์เฉพาะใดไฟล์หนึ่ง ดูตัวอย่าง
package main
import "embed"
//go:embed *
var static embed.FSคำสั่ง embed ต้องอยู่เหนือตัวแปร全局ที่มีประเภท embed.Fs 注意必须是ตัวแปร全局 และต้องใช้ต้องนำเข้าแพ็กเกจ embed ในตัวอย่างนี้ * หมายถึงจะแพ็กไฟล์ทั้งหมดในโฟลเดอร์ปัจจุบันเข้ากับไฟล์ไบนารี แต่จะไม่อนุญาตให้มีโฟลเดอร์ที่ขึ้นต้นด้วย .
ตัวอย่างด้านล่างนี้แสดงการอ่านเนื้อหาจากไฟล์ที่ฝัง
package main
import (
"embed"
"fmt"
)
//go:embed *.txt
var static embed.FS
func main() {
bytes, err := static.ReadFile("hello.txt")
if err != nil {
panic(err)
}
fmt.Println(string(bytes))
}มีเพียงสามเมธอด การใช้งานไม่แตกต่างจากระบบไฟล์ปกติ และเนื่องจากมันใช้งานอินเทอร์เฟซ io/Fs จึงสามารถส่งเป็นอ็อบเจกต์ Fs ได้
func (f FS) Open(name string) (fs.File, error)
func (f FS) ReadFile(name string) ([]byte, error)
func (f FS) ReadDir(name string) ([]fs.DirEntry, error)ตัวอย่างด้านล่างนี้แสดงการฝังไฟล์ html ผ่านคำสั่ง embed และเข้าถึงผ่านบริการ http
package main
import (
"embed"
"net/http"
)
//go:embed index.html
var htmlFs embed.FS
func main() {
http.Handle("/", http.FileServer(http.FS(htmlFs)))
http.ListenAndServe(":8080", http.DefaultServeMux)
}ผลลัพธ์การเข้าถึงมีดังนี้
$ curl -s -GET 127.0.0.1:8080
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world!</title>
</head>
<body>
<H1>Hello World!</H1>
<script>
alert("hello world!");
</script>
</body>
</html>คำสั่ง embed ยังรองรับประเภทตัวแปร全局เป็น []byte เช่น ตัวอย่างด้านล่างนี้
package main
import (
_ "embed"
"net/http"
)
//go:embed index.html
var rawdata []byte
func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
writer.Write(rawdata)
})
http.ListenAndServe(":8080", http.DefaultServeMux)
}ผลลัพธ์ที่บรรลุไม่แตกต่างจากตัวอย่างก่อนหน้า
$ curl -s -GET 127.0.0.1:8080
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world!</title>
</head>
<body>
<H1>Hello World!</H1>
<script>
alert("hello world!");
</script>
</body>
</html>build
ในส่วน build-การควบคุมการคอมไพล์ ได้กล่าวถึงการใช้คำสั่ง // +build เพื่อควบคุมพฤติกรรมการคอมไพล์ ส่วนคำสั่ง //go:build เป็นคำสั่งใหม่ที่ออกใน 1.17 ตั้งใจที่จะแทนที่คำสั่งก่อนหน้า แต่ตอนนี้ 1.21 ก็ยังไม่แทนที่ คาดว่าในอนาคตจะอยู่ร่วมกัน สำหรับคำสั่งใหม่นี้ เอกสารทางการก็มี介绍 build constraints ฟังก์ชันของมันไม่แตกต่างจากคำสั่งก่อนหน้า แต่ไวยากรณ์เข้มงวดกว่า รองรับนิพจน์บูลีน ดูตัวอย่าง
//go:build (linux && 386) || (darwin && !cgo)
package pkg_nameวิธีนี้อ่านได้ง่ายกว่าวิธีเดิมมาก
line
คำสั่ง line จะ影響หมายเลขบรรทัด หมายเลขคอลัมน์ และชื่อไฟล์ของบรรทัดถัดไป ฟังก์ชันของมันจำกัดเพียงเท่านี้ ส่วนใหญ่อาจใช้สำหรับดีบักข้อผิดพลาด เป็นต้น เช่น เมื่อเกิดข้อผิดพลาด จะเปลี่ยนข้อมูลที่คอมไพเลอร์เอาต์พุต
package main
var a undefinedType
func main() {
}โดยปกติ คอมไพเลอร์จะเอาต์พุต
.\main.go:3:7: undefined: undefinedTypeแต่หากใช้คำสั่ง line จะแตกต่าง
package main
//line abc.go:10:100
var a undefinedType
func main() {
}ดังนั้นเอาต์พุตของมันคือ
abc.go:10:106: undefined: undefinedTypeและเนื่องจากเหตุผลทางประวัติศาสตร์ คำสั่ง line เป็นคำสั่งเดียวที่มีการใช้งานแตกต่างจากคำสั่งอื่น รูปแบบของมันคือ
//line filename:line:columnจะเห็นว่าไม่จำเป็นต้องมี go: เป็นคำนำหน้า
linkname
การดำเนินการของคำสั่งนี้สามารถใช้ลิงก์ฟังก์ชันหรือตัวแปร全局ของแพ็กเกจอื่น แม้ว่าจะเป็นประเภทส่วนตัว การดำเนินการนี้มักปรากฏในไลบรารีมาตรฐานโดยเฉพาะ runtime มีฟังก์ชันบางฟังก์ชันที่ไม่มีฟังก์ชันบอดี้อาศัยวิธีนี้ในการ实现 อีกส่วนหนึ่งของฟังก์ชันบอดีว่างเปล่า则由汇编实现 ดูวิธีการใช้ รูปแบบการใช้งานมีดังนี้
//go:linkname 链接类型名称 被链接的类型และก่อนใช้ ต้องนำเข้าแพ็กเกจ unsafe ดูตัวอย่างง่าย ๆ ในการลิงก์ประเภทส่วนตัวในไลบรารีมาตรฐาน
import (
"fmt"
"unsafe"
)
//go:linkname memhash runtime.memhash
func memhash(p unsafe.Pointer, h, s uintptr) uintptr
func MemHash(data []byte) uint64 {
ptr := unsafe.Pointer(unsafe.SliceData(data))
return uint64(memhash(ptr, 0, uintptr(len(data))))
}
func main() {
fmt.Println(MemHash([]byte("hello")))
}เอาต์พุต
15395306441938000233มันลิงก์ฟังก์ชันส่วนตัว runtime.memhash เข้ากับฟังก์ชันที่เราประกาศเอง ฟังก์ชันนี้ไม่มีฟังก์ชันบอดีมีเพียง签名เท่านั้น ทำหน้าที่เป็นตัวพาเท่านั้น ฟังก์ชัน memhash คือกำหนดพอยน์เตอร์ เมล็ดแฮช และการเยื้องหน่วยความจำ คำนวณแฮชตามหน่วยความจำ กระบวนการลิงก์นี้เสร็จสิ้นในระหว่างการคอมไพล์
หากไม่ใช่ไลบรารีมาตรฐาน สถานการณ์จะแตกต่างเล็กน้อย เช่น มีฟังก์ชัน test หนึ่งฟังก์ชันภายใต้แพ็กเกจ example ก่อนลิงก์ต้องนำเข้าแพ็กเกจนี้แบบไม่ระบุชื่อก่อน
package example
// 一个私有类型,外界无法访问。
func test() string {
return "a"
}package main
import (
"fmt"
_ "golearn/example"
_ "unsafe"
)
//go:linkname test golearn/example.test
func test() string
func main() {
fmt.Println(test())
}เอาต์พุต
aจะเห็นว่าลิงก์สำเร็จแล้ว วิธีนี้สามารถเลี่ยงระบบโมดูลของ go ทำอะไรก็ได้ แต่ไม่แนะนำให้ใช้ในวงกว้าง เว้นแต่คุณจะรู้ว่าคุณกำลังทำอะไร
noinline
คำสั่ง noinline แสดงว่าฟังก์ชันห้ามเพิ่มประสิทธิภาพการ inline แม้ว่ามันจะง่ายมาก ดูตัวอย่างง่าย ๆ
package main
func val() string {
return "val"
}
func main() {
var c = val()
_ = c
}val เป็นฟังก์ชันที่ง่ายมาก ฟังก์ชันของมันคือคืนค่าสตริงลิเทอรัล เนื่องจากมันง่ายเกินไปและผลลัพธ์สามารถคาดเดาได้เสมอ ในการคอมไพล์จะถูกคอมไพเลอร์เพิ่มประสิทธิภาพเป็นรูปแบบดังนี้
package main
func main() {
var c = "val"
_ = c
}ดูรูปแบบ assembly ของมัน จะเห็นว่าไม่พบการเรียกฟังก์ชัน val
TEXT main.val(SB), NOSPLIT|NOFRAME|ABIInternal, $0-0
FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
LEAQ go:string."val"(SB), AX
MOVL $3, BX
FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
RETต่อไปเพิ่มคำสั่ง noinline
package main
//go:noinline
func val() string {
return "val"
}
func main() {
var c = val()
_ = c
}ดูรูปแบบ assembly อีกครั้ง
CMPQ SP, 16(R14)
PCDATA $0, $-2
JLS 17
PCDATA $0, $-1
PUSHQ BP
MOVQ SP, BP
FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
PCDATA $1, $0
CALL main.val(SB)
POPQ BP
RETครั้งนี้สามารถเห็นการเรียก main.val ได้อย่างชัดเจน และนี่คือฟังก์ชันที่คำสั่ง noinline ทำหน้าที่ ป้องกันการ inline ฟังก์ชันเมื่อคอมไพเลอร์เพิ่มประสิทธิภาพ
nospilit
คำสั่ง nospilit ทำหน้าที่ข้ามการตรวจสอบสแต็กโอเวอร์โฟลว์ เนื่องจากโมเดลการกำหนดการพร้อมกันของ go เป็นการกำหนดการแบบแย่งชิง สมมติว่าฟังก์ชันหนึ่งจะรันโค้ดระดับต่ำมาก โค้ดอื่นเมื่อเรียกฟังก์ชันนี้ไม่เหมาะที่จะถูกแย่งชิง สามารถใช้คำสั่งนี้เพื่อแสดง
//go:nosplit
func nospilitFn()หลังใช้คำสั่งนี้ จะไม่มีการเติบโตของสแต็กอีกต่อไป
noescape
noescape จากชื่อของมันสามารถเดาได้ง่ายว่าเกี่ยวข้องกับการ逃逸 ฟังก์ชันของมันคือแสดงว่าฟังก์ชันปัจจุบันจะไม่เกิดพฤติกรรมการ逃逸ของหน่วยความจำ หลังดำเนินการทรัพยากรทั้งหมดถูกกู้คืน และฟังก์ชันนี้ต้องมีเพียง签名ไม่มีฟังก์ชันบอดี ในสถานการณ์นี้โดยทั่วไปการ实现ของฟังก์ชัน则由汇编实现
เช่น memhash ที่ใช้ก่อนหน้านี้จะใช้คำสั่งนี้
//go:noescape
//go:linkname memhash runtime.memhash
func memhash(p unsafe.Pointer, h, s uintptr) uintptrเช่นนี้ คอมไพเลอร์จะไม่ทำการวิเคราะห์การ逃逸สำหรับมัน เงื่อนไขคือคุณต้องรับประกันว่ามันจะไม่เกิดการ逃逸 หากเกิด ก็ไม่รู้ว่า会有什么后果
uintptrescapes
คำสั่ง uintptrescapes แสดงว่าพารามิเตอร์ประเภท uinptr ในฟังก์ชันนี้ถูกแปลงเป็นค่าพอยน์เตอร์และ逃逸ไปยังฮีป และต้องรักษาให้存活 คำสั่งนี้มักใช้สำหรับการเรียกใช้ระบบระดับต่ำ ส่วนใหญ่ไม่จำเป็นต้องเข้าใจ
//go:uintptrescapes
func nospilit(ptr uintptr) uintptrในอดีตควรมีคำสั่ง notinheaps สำหรับแสดงว่าประเภทไม่อนุญาตให้จัดสรรหน่วยความจำไปยังฮีป ไม่ทราบว่าถูกลบในเวอร์ชันใด
norace
คำสั่ง norace แสดงว่าการเข้าถึงหน่วยความจำของฟังก์ชันไม่จำเป็นต้องวิเคราะห์ race condition มักใช้เมื่อรันโค้ดระดับต่ำไม่เหมาะสำหรับการวิเคราะห์ race condition
//go:norace
func low_level_code(ptr uintptr) uintptrTIP
ยังมีคำสั่งบางคำสั่งที่จำกัดให้ใช้โดยแพ็กเกจ runtime เท่านั้น ภายนอกไม่สามารถใช้ได้ พวกมันจะเกี่ยวข้องกับสิ่งที่ลึกกว่า หากต้องการเข้าใจสามารถดู介绍เกี่ยวกับพวกมันได้ที่ Runtime-only compiler directives
