Skip to content

Baris Perintah

Perintah di Go mencakup satu set toolchain lengkap yang mencakup dokumentasi, pemformatan, pemeriksaan kode, kompilasi, pengujian, manajemen dependensi, dan berbagai aspek pengembangan Go.

text
bug         Laporkan kerentanan
build       Kompilasi paket dan dependensi
clean       Hapus file objek
doc         Tampilkan dokumentasi dalam kode sumber
env         Lihat informasi variabel lingkungan Go
fix         Perbaiki masalah kompatibilitas API akibat perubahan versi go
fmt         Pemformatan kode sumber
generate    Pembuatan kode
get         Tambahkan dependensi
install     Instal dan kompilasi paket
list        Perintah daftar paket/modul
mod         Perintah pemeliharaan modul
work        Perintah pemeliharaan workspace
run         Kompilasi dan jalankan
test        Uji
tool        Jalankan alat go yang ditentukan
version     Tampilkan informasi versi go
vet         Pindai dan tampilkan masalah potensial dalam kode sumber

Artikel ini hanya menjelaskan penggunaan mereka secara sederhana, semua konten mengacu pada dokumentasi resmi, jika ingin mempelajari lebih detail silakan kunjungi cmd/go.

help

Perintah pertama yang harus dikenali adalah perintah help, yang dapat digunakan untuk membaca penggunaan perintah. Ada dua cara penggunaan, jika ingin mendapatkan informasi penggunaan singkat, Anda dapat menambahkan flag -h setelah perintah yang ditentukan, misalnya

sh
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.

go akan menampilkan penggunaan perintah dengan singkat, juga memberi tahu bahwa untuk mendapatkan informasi lebih detail perlu menggunakan perintah help

sh
$ 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'.

Manfaatkan perintah help dengan baik, melalui itu Anda bisa mendapatkan banyak informasi tentang perintah.

doc

sh
$ 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

Perintah doc akan menampilkan komentar dokumentasi untuk paket, konstanta, fungsi, tipe, variabel, metode, atau bahkan field struct yang ditentukan. Tanpa parameter apa pun, akan menampilkan komentar paket saat ini

sh
$ go doc

Juga dapat menentukan paket tertentu untuk dilihat, misalnya melihat dokumentasi paket runtime

sh
$ 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.
......

Atau tipe tertentu

sh
$ 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.
      ...

Atau fungsi tertentu

sh
$ 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.

Memiliki flag berikut yang umum digunakan

  • -u: Lihat tipe privat
  • -all: Lihat semua dokumentasi paket yang ditentukan
  • -short: Hanya deskripsi singkat satu baris
  • -src: Tampilkan kode sumber
  • -cmd: Untuk beberapa paket yang merupakan perintah go, juga tampilkan dokumentasi kode di dalam paket.

Misalnya melihat variabel runtime.inf, yang merupakan variabel yang tidak diekspor

sh
$ go doc -u runtime.inf
package runtime // import "runtime"

var inf = float64frombits(0x7FF0000000000000)

Manfaatkan perintah doc dengan baik dapat membantu Anda membaca dokumentasi dengan lebih mudah.

Cara lain untuk membaca dokumentasi perintah adalah dengan membaca kode sumber, karena beberapa dokumentasi perintah tidak ditulis dengan terlalu detail, sebaliknya dalam kode sumber akan ada penjelasan yang lebih rinci. Karena semua perintah ini ditulis dengan go, membacanya juga sangat mudah. Perintah-perintah ini semuanya berada di paket src/cmd, setiap sub-paket adalah perintah terpisah, entry point berada di file cmd/go/main.go

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,
    }
}

Di sini Anda akan menemukan semua sub-perintah go, serta informasi dokumentasi bantuan mereka.

bug

sh
$ go help bug
usage: go bug

Bug opens the default browser and starts a new bug report.
The report includes useful system information.

Perintah ini tidak memiliki parameter atau flag apa pun, akan menggunakan browser default Anda untuk mengakses halaman issue repositori github.com/golang/go, memudahkan Anda untuk memberikan feedback bug, selain itu tidak ada fungsi lain.

version

Melalui perintah version dapat melihat informasi versi go saat ini.

go
$ go version -h
usage: go version [-m] [-v] [file ...]

Tanpa parameter apa pun, akan menampilkan versi bahasa go saat ini

sh
$ go version
go version go1.21.0 windows/amd64

Juga menerima path file sebagai parameter, akan menampilkan versi go yang digunakan saat mengkompilasi semua file biner yang dapat diidentifikasi di path tersebut.

sh
$ 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

Parameter -v menentukan perintah version untuk mencoba menampilkan versi go dari file yang tidak dapat diidentifikasi, parameter -m menampilkan informasi modul file biner, serta beberapa parameter kompilasi, berikut adalah contoh sederhana.

sh
$ 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=v1

go sendiri adalah file biner, sebenarnya tanpa parameter apa pun, go version menampilkan versi bahasa go dari file biner itu sendiri, karena semua toolchain cmd/go diimplementasikan oleh bahasa go itu sendiri.

env

Melalui perintah env dapat melihat semua informasi variabel lingkungan go, mengubah variabel lingkungan ini akan mempengaruhi perilaku toolchain go.

sh
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.

Jalankan perintah ini tanpa parameter apa pun, akan menampilkan nilai semua variabel lingkungan go

sh
$ go env
set GO111MODULE=on
set GOARCH=amd64
...

Menambahkan nama variabel lingkungan tertentu sebagai parameter hanya dapat menampilkan nilai variabel tersebut

sh
$ go env GO111MODULE
on

Menambahkan -json dapat menampilkan format json

sh
$ go env -json
{
        "AR": "ar",
        "CC": "gcc",
    ......
}

Melalui flag -w, dan dengan parameter dalam bentuk var=value, akan mengubah nilai variabel tertentu secara permanen

sh
$ go env -w GO111MODULE=on

Menggunakan flag -u, dapat mengembalikan variabel tertentu ke nilai default

sh
$ go env -u GO111MODULE

Jalankan go help environment untuk melihat pengenalan setiap variabel lingkungan

sh
$ 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.
    ......

Berikut adalah pengenalan beberapa variabel lingkungan yang umum digunakan

GOVERSION

Nilai variabel lingkungan ini tergantung pada versi bahasa go, dan nomor versi berasal dari file $GOROOT/VERSION, yang mencatat versi go saat ini dan waktu build.

sh
$ cat $GOROOT/VERSION
go1.21.3
time 2023-10-09T17:04:35Z

Nilai variabel runtime.Version sama dengan nilai GOVERSION, dan variabel lingkungan ini tidak dapat dimodifikasi.

GOENV

Di direktori $GOROOT akan ada file konfigurasi default bernama go.env

sh
$ 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

Formatnya sederhana yaitu key=value, nilai variabel lingkungan yang dimodifikasi melalui perintah go env -w key=value akan ditulis ke file konfigurasi. Namun juga dapat tidak menggunakan file konfigurasi default, variabel lingkungan GOENV dapat secara manual menentukan alamat file konfigurasi env, dan nilai variabel lingkungan GOENV hanya dapat ditimpa oleh variabel lingkungan sistem operasi, tidak dapat dimodifikasi oleh perintah go env -w.

GOHOSTARCH

Mewakili arsitektur CPU mesin ini, hanya untuk tampilan, nilai variabel lingkungan ini tidak dibaca dari file konfigurasi, dan tidak dapat dimodifikasi.

GOHOSTOS

Mewakili sistem operasi mesin ini, hanya untuk tampilan, nilai variabel lingkungan ini tidak dibaca dari file konfigurasi, dan tidak dapat dimodifikasi.

GOOS

Saat kompilasi, nilai GOOS akan menentukan sistem target mana kode sumber dikompilasi menjadi file biner, nilai default adalah GOHOSTOS, yaitu sistem operasi mesin ini, memiliki beberapa pilihan berikut

  • linux
  • darwin
  • windows
  • netbsd
  • aix
  • android

Sistem operasi yang didukung sebenarnya tidak hanya ini, gunakan perintah go tool dist list, lihat semua nilai yang didukung

sh
$ 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
windows

GOARCH

Saat kompilasi, nilai GOARCH akan menentukan arsitektur CPU mana yang digunakan saat kompilasi, nilai default adalah GOHOSTARCH, yaitu arsitektur CPU mesin ini, memiliki beberapa pilihan berikut

  • amd64
  • 386
  • arm
  • ppc64

Arsitektur yang didukung sebenarnya tidak hanya ini, gunakan perintah go tool dist list, lihat semua nilai yang didukung

sh
$ 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

Perlu dicatat bahwa GOOS dan GOARCH tidak dapat dikombinasikan secara sembarangan, beberapa sistem operasi hanya dapat mendukung arsitektur CPU tertentu.

GOROOT

GOROOT mewakili direktori root lokasi instalasi bahasa go, nilai GOROOT tidak dapat dimodifikasi secara langsung, dan hanya dapat ditimpa oleh variabel lingkungan sistem operasi.

sh
$ ls $GOROOT -1
api
bin
codereview.cfg
CONTRIBUTING.md
doc
go.env
lib
LICENSE
misc
PATENTS
pkg
README.md
SECURITY.md
src
test
VERSION

Di direktori root terdapat beberapa folder atau file yang cukup penting

  • lib, menyimpan beberapa dependensi, saat ini hanya ada satu library yang berisi informasi zona waktu berbagai negara di dunia, berada di $GOROOT/lib/time, file biner yang dikompilasi tidak akan menyertakan informasi zona waktu ini.

  • pkg, menyimpan beberapa library alat dan file header, misalnya perintah go tool akan mencari file biner toolchain go di direktori $GOROOT/pkg/tool

  • bin, menyimpan file biner, secara default hanya ada dua file eksekusi go dan gofmt, $GOROOT/bin harus ditambahkan ke variabel sistem, jika tidak perintah go tidak dapat digunakan.

  • src, menyimpan kode sumber go

  • VERSION, file ini menyimpan informasi versi bahasa go

  • go.env, file ini adalah file konfigurasi env default

GOPATH

Nilai default GOPATH adalah $HOME/go, nilai variabel lingkungan ini menentukan ke mana harus pergi untuk mencari file yang diimpor saat mengurai pernyataan import. Di masa awal ketika tidak ada gomod, GOPATH khusus digunakan untuk menyimpan berbagai library pihak ketiga, strukturnya adalah sebagai berikut

sh
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)

Setelah gomod lahir, GOPATH hanya menjadi tempat untuk menyimpan dependensi yang diunduh oleh go get, serta untuk menyimpan file biner yang diunduh dan dikompilasi oleh go install. Perlu dicatat bahwa lokasi GOPATH tidak boleh sama dengan GOROOT, jika tidak tidak akan berfungsi.

sh
$ go env GOBIN
warning: GOPATH set to GOROOT (/home/user/go) has no effect

Hingga saat penulis menulis artikel ini, versi bahasa go sudah mencapai go1.21.3, kecuali proyek yang sangat kuno, hampir tidak ada orang yang akan menggunakan gopath untuk mengelola dependensi lagi.

GOBIN

GOBIN digunakan untuk menyimpan file eksekusi biner pihak ketiga yang diunduh dan dikompilasi oleh go install, nilai defaultnya adalah $GOPATH/bin. Sama seperti $GOROOT/bin, direktori ini harus ditambahkan ke variabel lingkungan sistem operasi, jika tidak juga tidak dapat menggunakan file biner di direktori GOBIN.

GOMODCACHE

GOMODCACHE menunjukkan lokasi penyimpanan dependensi yang diunduh oleh go get, nilai defaultnya adalah $GOPATH/pkg/mod. Format penyimpanannya adalah sebagai berikut

$GOMODCACHE/domain/username/project@verion

Di direktori tingkat yang sama akan ada folder bernama sumdb, digunakan untuk menyimpan informasi terkait database checksum dependensi.

GOCACHE

Menyimpan informasi cache yang digunakan untuk kompilasi, nilai defaultnya adalah $HOME/.cache/go-build, direktori ini akan menghasilkan file README.

sh
$ 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.

Setiap build akan menghasilkan banyak file, go akan meng-cache file-file ini untuk digunakan kembali saat kompilasi berikutnya.

GOTEMPDIR

Digunakan untuk file sementara yang dihasilkan saat kompilasi, misalnya file biner sementara yang akan dijalankan oleh go run. Nilai defaultnya adalah direktori sementara yang ditentukan oleh sistem operasi, di mac atau linux adalah /tmp, di windows adalah %TEMP%, juga dapat dimodifikasi ke lokasi yang ditentukan pengguna.

GO111MODULE

Variabel lingkungan ini menunjukkan cara mana yang digunakan untuk mengelola dependensi proyek go, memiliki tiga nilai yang tersedia

  • off, matikan gomod, gunakan gopath, dan abaikan semua file go.mod
  • on, gunakan gomod, jangan gunakan gopath (default).
  • auto, deteksi otomatis, jika file proyek berisi go.mod akan menggunakan gomod untuk manajemen

TIP

Mengapa disebut GO111MODULE, tidak langsung disebut GOMODULE, karena gomod pertama kali diluncurkan pada versi go1.11.

GOPROXY

Proxy modul go, nilai defaultnya adalah https://proxy.golang.org,direct, url dipisahkan dengan koma, direct berarti langsung menggunakan VCS untuk melewati proxy modul, hanya akan menjalankan yang后者 ketika yang pertama tidak dapat diakses, ada pilihan lain yang tersedia yaitu off, yang berarti melarang pengunduhan modul apa pun. Selain itu, GOPROXY juga dapat berupa alamat file, misalnya

GOPROXY=file://$(go env GOMODCACHE)/cache/download

Melalui go get -x dapat melihat perintah yang dijalankan selama proses pengunduhan dependensi, dapat mengetahui apakah menggunakan proxy.

sh
$ 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/0/x068/334
# 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: 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

Menggunakan proxy modul dapat secara efektif meningkatkan kecepatan pengunduhan modul, pengguna di Tiongkok pada dasarnya tidak menggunakan proxy tidak akan dapat mengakses proxy default resmi, saat ini proxy modul pihak ketiga publik dan tepercaya adalah sebagai berikut

  • https://proxy.golang.com.cn, open source sekaligus menyediakan layanan versi enterprise
  • https://goproxy.cn, disediakan dan open source oleh Qiniu Cloud

Tentu saja ada solusi proxy modul self-hosted open source: goproxy

GOSUMDB

GOSUMDB digunakan untuk mengatur alamat database deteksi checksum library dependensi, defaultnya adalah sum.golang.org, ketika Anda mengatur proxy, go akan mengakses database checksum melalui proxy.

GOPRIVATE

Variabel lingkungan GOPRIVATE digunakan untuk mengatur library privat, library yang cocok tidak akan divalidasi melalui sumdb, juga tidak akan melalui proxy, akan mengunduh dependensi langsung melalui VCS. Mendukung pengaturan wildcard, dipisahkan dengan koma, seperti yang ditunjukkan di bawah ini, semua dependensi dengan akhiran corp.example.com dan bernama github.com/gohper/myproject tidak akan melalui proxy dan sumdb.

GOPRIVATE=*.corp.example.com,github.com/gohper/myproject

Juga dapat langsung mengatur pengguna atau organisasi tertentu

GOPRIVATE=github.com/gopher,github.com/myorganization

GONOPROXY

Menunjukkan dependensi mana yang tidak perlu melalui proxy, aturannya sama dengan GOPRIVATE, dan akan menimpa GOPRIVATE.

GONOSUMDB

Menunjukkan dependensi mana yang tidak perlu melalui database checksum, aturannya sama dengan GOPRIVATE, dan akan menimpa GOPRIVATE.

GOINSECURE

Menunjukkan dependensi mana yang langsung diunduh menggunakan VCS, aturannya sama dengan GOPRIVATE, dan akan ditimpa oleh GONOPROXY dan GONOSUMDB.

GOVCS

Mengatur sistem kontrol versi manajemen modul, default public:git|hg,private:all. Juga dapat membatasi VCS domain tertentu, misalnya

GOVCS=github.com:git,evil.com:off,*:git|hg

Dalam batasan di atas, github hanya bisa menggunakan git, evil.com tidak diizinkan, menggunakan | dapat menunjukkan beberapa VCS. Jika tidak membuat batasan apa pun, dapat diatur seperti berikut

GOVCS=*:all

Jika tidak mengizinkan penggunaan VCS apa pun, dapat diatur seperti berikut

GOVCS=*:off

GOWORK

Mengatur apakah workspace diaktifkan, default kosong yaitu diaktifkan, jika diatur ke off, maka tidak diaktifkan, akan mengabaikan semua file go.work.

GOTOOLDIR

Mengatur lokasi toolchain go yang akan digunakan, defaultnya adalah $GOROOT/pkg/tool, toolchain default juga disimpan di lokasi ini.

GODEBUG

Mengatur opsi debug, mengontrol beberapa perilaku eksekusi program go dalam bentuk key-value, misalnya

GODEBUG=http2client=0,http2server=0

Pengaturan ini untuk memudahkan go kembali ke perilaku lama ketika ada perubahan yang tidak kompatibel selama pembaruan versi, misalnya di 1.21 tidak lagi mengizinkan situasi panic(nil) terjadi, untuk ini, go resmi secara khusus mencatat GODEBUG History, kunjungi GODEBUG untuk mempelajari lebih detail.

CGO_ENABLED

Menunjukkan apakah cgo diaktifkan, defaultnya 1, yaitu diaktifkan, diatur ke 0 maka dimatikan.

Variabel lingkungan di atas adalah yang umum digunakan, untuk beberapa yang tidak begitu umum tidak akan diperkenalkan terlalu banyak, seperti CGO, WASM, dll., jika tertarik dapat mempelajarinya sendiri.

build

Go mendukung dua jenis kompiler, gccgo dan gc. gcc adalah kompiler c/c++ lama yang mendukung berbagai bahasa termasuk go, yang后者 gc bukan berarti garbage collection, ini mengacu pada go compiler, bahasa go menyelesaikan bootstrap pada go1.5, gc adalah kompiler yang sepenuhnya ditulis dalam bahasa go, kode sumbernya berada di paket cmd/compile, karena sepenuhnya diimplementasikan dalam bahasa go, sangat mudah untuk memahami dan mempelajari mekanisme internalnya. Secara default, kompiler menggunakan gc untuk kompilasi. Ngomong-ngomong, debugger bahasa go juga terbagi dua, gdb dan dlv, yang pertama adalah debugger c/c++ lama yang mendukung berbagai bahasa termasuk go, yang后者 adalah debugger yang ditulis dalam bahasa go, dukungan untuk bahasa go lebih ramah, juga open source, direkomendasikan untuk menggunakan yang后者. Perintah build digunakan untuk mengkompilasi file sumber go menjadi file biner yang dapat dieksekusi, Anda akan mengalami pengalaman kompilasi yang sangat cepat, ini juga merupakan salah satu karakteristik bahasa go.

sh
$ go build -h
usage: go build [-o output] [build flags] [packages]
Run 'go help build' for details.

Menerima tiga parameter, satu adalah path output file yang ditunjukkan oleh flag -o, satu adalah flag build untuk mendefinisikan perilaku kompilasi build flags, yang terakhir adalah paket yang akan dikompilasi, parameter ini harus diletakkan di akhir. Berikut adalah contoh sederhana, tidak menggunakan flag build.

sh
# Windows
$ go build -o .\bin\golearn.exe golearn

# macOS / Linux
$ go build -o ./bin/golearn golearn

./bin/golearn.exe menunjukkan path output, golearn menunjukkan modul yang akan dikompilasi, juga dapat berupa file entry atau folder. Misalnya contoh sederhana di bawah ini adalah dengan main.go file entry sebagai target kompilasi.

sh
# Windows
$ go build -o .\bin\golearn.exe main.go

# macOS / Linux
$ go build -o ./bin/golearn main.go

Saat kompilasi akan mengabaikan semua file yang berakhiran _test.go, karena sesuai konvensi file-file tersebut adalah file testing.

Selain itu, perintah build juga mendukung banyak flag build untuk mengontrol beberapa perilaku saat kompilasi.

  • -x: Tampilkan instruksi detail selama proses kompilasi
  • -n: Mirip dengan -x, tetapi perbedaannya hanya menampilkan instruksi tersebut, tetapi sebenarnya tidak mengeksekusinya.
  • -v: Tampilkan paket yang dikompilasi
  • -p: Jumlah konkurensi selama proses kompilasi
  • -a: Paksa build ulang, meskipun sudah yang terbaru.
  • -compiler: Tentukan kompiler mana yang digunakan, gccgo atau gc, yang后者 adalah kompiler yang ditulis oleh go.
  • -race: Aktifkan deteksi race condition
  • -msan: Aktifkan analisis memori
  • -asan: Aktifkan analisis alamat
  • -cover: Aktifkan deteksi coverage kode
  • -buildmode: Tentukan mode kompilasi, ada pilihan archive, c-archive, c-shared, default, shared, exe, pie, plugin.
  • -pgo, tentukan file pgo
  • -trimpath: Hapus prefix path file sumber, misalnya path relatif /var/lib/go/src/main.go, setelah dihapus nama file yang diperoleh melalui runtime saat runtime hanya path relatif terhadap path modul /main.go, setelah mengaktifkan item ini, waktu kompilasi akan meningkat secara signifikan, sekitar 20-40%, tergantung pada jumlah file.
  • -toolexec, beberapa perintah go yang dieksekusi sebelum kompilasi, formatnya adalah -toolexec 'cmd args'.
  • -gcflags: Tentukan beberapa tag kompiler gc
  • -gccgoflags: Tentukan beberapa tag kompiler gccgo
  • -ldflags: Tentukan beberapa tag alat link

Untuk beberapa parameter passing seperti ldflags, dapat mengirim parameter seperti "-help" untuk mendapatkan nilai yang mungkin, misalnya

sh
$ 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
......

Di atas adalah yang umum digunakan, untuk yang lain yang tidak begitu umum dapat dipelajari sendiri.

gcflags

Melalui gcflags dapat mengirim beberapa parameter ke kompiler gc untuk mengontrol perilaku tertentu, format penggunaannya adalah -gcflags="pattern=args list", args list adalah daftar parameter, pattern adalah cakupan, ada beberapa nilai yang tersedia

  • main, path paket tingkat atas tempat file entry berada
  • all, modul saat ini dan semua dependensi dalam mode saat ini
  • std, library standar
  • cmd, berlaku untuk semua file sumber di paket cmd
  • Wildcard, seperti ., ./..., cmd/....

Aturan pattern ini berlaku untuk semua flag yang mendukung format ini, misalnya ldflags. Lihat nilai parameter yang tersedia melalui perintah berikut

sh
$ go build -gcflags -help
用法:compile [选项] file.go...
  -%    调试非静态初始化器
  -+    编译运行时
  -B    禁用边界检查
  -C    禁用错误消息中的列号打印
  -D path
        设置本地导入的相对路径
  -E    调试符号导出
  -I directory
        添加目录到导入搜索路径
  -K    调试缺失的行号
  -L    对于受 //line 指令影响的错误位置,同时显示实际源文件名
  -N    禁用优化
  -S    打印汇编列表
  -V    打印版本并退出
  -W    类型检查后调试解析树
  ......

Berikut adalah pengenalan beberapa parameter yang umum digunakan

  • -S: Tampilkan bentuk assembly kode
  • -N: Matikan optimasi kompilasi
  • -m: Tampilkan keputusan optimasi
  • -l: Matikan inline fungsi
  • -c: Jumlah konkurensi kompilasi
  • -dwarf: Hasilkan tanda DWARF

Misalnya jika ingin melihat bentuk assembly kode, dapat menggunakan parameter -S, dan juga harus mematikan optimasi dan inline, baru dapat mengembalikan bentuk aslinya, seperti berikut

sh
$ 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

Melalui ldflags dapat mengirim beberapa parameter ke linker untuk mengontrol perilaku tertentu, lihat semua nilai yang tersedia untuk ldflags melalui perintah berikut, hampir dua puluh tiga.

sh
$ 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)
  .....

Parameter -X dari ldflags adalah fungsi yang sangat praktis, dapat mendefinisikan nilai variabel string paket yang ditentukan saat linking. Melalui fungsi ini, kita dapat dengan mudah menyuntikkan beberapa informasi meta saat kompilasi. Dan ini hanya variabel, jadi juga mudah untuk mendapatkannya saat runtime, berikut adalah contoh sederhana.

go
package main

import "fmt"

var (
  Version string
)

func main() {
  fmt.Println(Version)
}

Jalankan perintah

sh
go build -ldflags "-X main.Version=$(git describe --always)" main.go

Setelah dijalankan akan menampilkan checksum sha1 commit git.

5e3fd7a

Beberapa parameter lain yang cukup praktis adalah

  • -w: Tidak menghasilkan DWARF, ini adalah informasi yang memudahkan debug kode sumber.
  • -s: Nonaktifkan tabel simbol

Kedua ini biasanya digunakan bersama, dapat secara signifikan mengurangi ukuran file biner setelah kompilasi, sekitar 40%-50%, kekurangannya juga jelas, tidak dapat melakukan debug, berikut adalah contoh.

sh
$ go build -ldflags="-w -s" main.go

Kompilasi Silang

Kompilasi bahasa go selalu memiliki dua karakteristik besar, yang pertama adalah cepat, karakteristik besar lainnya adalah kompilasi silang, kompilasi silang berarti dapat mengkompilasi kode target sistem lain di lokal, misalnya di windows mengkompilasi menjadi file biner di linux atau darwin, sebaliknya juga sama. Bahasa yang mendukung kompilasi silang sangat banyak, ini bukan hal yang aneh, tetapi kompilasi silang bahasa go sangat sederhana, hanya perlu dua langkah berikut

  1. Atur variabel lingkungan GOOS, pilih sistem operasi target Anda
  2. Atur variabel lingkungan GOARCH, pilih arsitektur CPU target Anda
  3. Gunakan go build untuk kompilasi seperti biasa

Seluruh proses sangat singkat, tidak perlu menggunakan alat atau konfigurasi tambahan, dan kecepatannya sama cepatnya dengan biasanya. Seperti yang ditunjukkan di bawah ini

makefile
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

Langkah pertama SET CGO_ENABLED=0 ini menonaktifkan cgo, sekali kode Anda menggunakan cgo, maka tidak dapat menggunakan kompilasi silang dengan normal. Langkah kedua SET GOOS mengatur sistem target, pilihan yang tersedia adalah linux, darwin, windwos, netbsd. Langkah ketiga mengatur arsitektur CPU, SET GOARCH, pilihan yang tersedia adalah amd64, 386, arm, ppc64. Langkah terakhir adalah melakukan kompilasi seperti biasa.

Kontrol Kompilasi

Perintah build dapat mencapai efek kontrol kompilasi melalui tags, ini ada dalam kode sumber dalam bentuk instruksi, lihat contoh, file product.go

go
// +build product

package main

import "fmt"

func main() {
  fmt.Println("product")
}

File debug.go

go
// +build debug

package main

import "fmt"

func main() {
  fmt.Println("debug")
}

Keduanya memiliki instruksi // +build, menunjukkan dalam situasi apa mereka akan dikompilasi. Format dasarnya adalah

go
// +build tag1 tag2

package pkg_name

Ada beberapa aturan yang harus dipatuhi

  1. // dan +build harus dipisahkan satu spasi
  2. Harus berada di atas deklarasi paket
  3. Harus dipisahkan satu baris kosong dengan deklarasi paket

Selain itu, juga dapat mencapai tujuan kontrol logika melalui interval sederhana, spasi menunjukkan OR, koma menunjukkan AND, ! menunjukkan NOT. Misalnya contoh di bawah ini

go
// +build windows linux

package pkg_name

Menunjukkan bahwa di platform windows atau linux file saat ini akan dikompilasi.

go
// +build windows,amd64,!cgo linux,i386,cgo

package pkg_name

Contoh ini menunjukkan bahwa hanya akan dikompilasi di platform windows arsitektur amd64 dan tidak mengaktifkan cgo atau di platform linux arsitektur i386 dan mengaktifkan cgo. Jika Anda hanya tidak ingin membiarkan file tertentu tidak ikut dalam kompilasi, dapat menggunakan ignore.

go
// +build ignore

package pkg_name

Juga dapat ada instruksi multi-baris

go
// +build windows
// +build amd64

package pkg_name

Instruksi multi-baris ditangani dengan cara AND. Untuk tag platform dan arsitektur ini, saat kompilasi go akan mengirim secara otomatis, kita juga dapat mengirim tag kustom, ambil dua file paling awal sebagai contoh

sh
$ go build -tags="debug" . && ./golearn.exe
debug

$ go build -tags="product" . && ./golearn.exe
product

Dapat melihat output berbeda saat mengirim tag berbeda, tujuan kontrol kompilasi juga tercapai.

run

Perintah run dan build keduanya akan mengkompilasi kode sumber, perbedaannya adalah perintah run akan langsung menjalankan setelah kompilasi selesai. Perintah run untuk mempercepat kecepatan kompilasi, tidak menghasilkan informasi debug selama proses kompilasi, jadi juga tidak mendukung debug, dan hanya menghasilkan file biner sementara, biasanya disimpan di direktori GOTMEPDIR, misalnya /temp/go-build2822241271/b001/exe/main.exe.

sh
$ go run -h
usage: go run [build flags] [-exec xprog] package [arguments...]
Run 'go help run' for details.

Juga mendukung flag build perintah build, juga menyediakan parameter -exec untuk menunjukkan program mana yang akan menjalankan file biner, [arguments...] mengacu pada parameter running program. Berikut adalah contoh

go
package main

import (
  "fmt"
  "os"
)

var (
  Version string
)

func main() {
  fmt.Println(Version)
  fmt.Println(os.Args[1:])
}

Gunakan go run untuk menjalankan

sh
$ go run -ldflags="-X main.Version=$(git describe --always)" main.go hello
5e3fd7a
[hello]

Secara keseluruhan penggunaan tidak terlalu berbeda dengan go build, tidak akan dijelaskan terlalu banyak.

tool

Perintah tool sendiri tidak memiliki fungsi apa pun, fungsinya adalah langsung memanggil alat di direktori cmd/, misalnya cmd/compile adalah kompiler bawaan. Melalui go tool dapat langsung memanggil alat-alat ini, tidak perlu menjalankan file biner alat-alat ini secara manual.

sh
$ go tool -h
usage: go tool [-n] command [args...]

Gunakan parameter -n untuk mencetak semua parameter perintah yang didukung

sh
$ go tool -n
addr2line
asm
buildid
cgo
compile
covdata
cover
doc
fix
link
nm
objdump
pack
pprof
test2json
trace
vet

Alat-alat ini disimpan di direktori GOROOT/pkg/tool, dan dikelompokkan berdasarkan sistem operasi dan arsitektur CPU, seperti berikut.

sh
$ 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*

Gunakan format go doc cmd/command untuk melihat penggunaan setiap perintah, misalnya

sh
$ 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.
...

Parameter flag yang didukung oleh cmd/compile, juga merupakan parameter yang didukung oleh gcflags yang disebutkan sebelumnya. Perbedaan go tool compile dan go build adalah, yang pertama hanya bertanggung jawab untuk kompilasi, dan hanya dapat menggunakan file sebagai parameter, yang后者 dapat menggunakan folder, paket, file sebagai parameter, dan tidak hanya melakukan kompilasi kode sumber, juga bertanggung jawab untuk linking file, menghapus file yang tidak berguna, dll., yang pertama adalah bagian dari yang后者. Kita dapat mencetak perintah yang dieksekusi selama proses build

sh
$ 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
...

Dalam proses dapat melihat ada bagian /golang/pkg/tool/windows_amd64/compile.exe ini,正是 memanggil kompiler. Selain compile, masih banyak alat yang dapat dipanggil, banyak perintah go sebenarnya adalah alias mereka.

clean

Perintah clean digunakan untuk menghapus file objek yang dihasilkan selama proses kompilasi

sh
$ go clean -h
usage: go clean [clean flags] [build flags] [packages]
Run 'go help clean' for details.

Mendukung flag berikut

  • -i: Hapus file arsip atau file biner yang sesuai
  • -n: Cetak perintah yang akan dieksekusi selama proses pembersihan tetapi sebenarnya tidak mengeksekusi
  • -x: Cetak perintah yang akan dieksekusi selama proses pembersihan dan eksekusi
  • -r: Hapus secara rekursif melalui import path
  • -cache, hapus semua cache yang dihasilkan oleh go build
  • -testcache: Hapus semua cache testing yang dihasilkan
  • -modcache: Hapus semua cache modul yang diunduh
  • -fuzzcache: Hapus cache yang dihasilkan oleh fuzz test.

Ketika menggunakan go tool compile, adalah langsung memanggil perintah kompiler, tidak seperti go build yang akan melakukan banyak penanganan afterwards, akan menghasilkan file objek. Misalnya jalankan perintah berikut

sh
go tool compile -N -S -l main.go

Akan menghasilkan file bernama main.o, gunakan perintah go clean untuk menghapus. Atau gunakan parameter -n untuk mencetak perintah yang akan dieksekusi.

sh
$ 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

Hapus cache kompilasi, ini akan menghapus cache kompilasi yang dihasilkan di direktori GOCACHE

sh
$ go clean -cache -n
rm -r /cache/00 /cache/01 /cache/02

Hapus cache yang dihasilkan oleh fuzz test, cache ini secara default disimpan di direktori GOCACHE/fuzz/

sh
$ go clean -fuzzcache -n
rm -rf /cache/fuzz

fix

Bahasa go hingga saat penulis menulis artikel ini sudah sepuluh tahun, selama proses pembaruan dan modifikasi bahasa yang terus-menerus, pasti akan muncul beberapa ketidakkompatibelan karena perubahan API, perintah fix lahir untuk ini, akan mendeteksi API yang sudah usang dalam file sumber dan menggantinya dengan API baru.

sh
$ go fix -h
usage: go fix [-fix list] [packages]
Run 'go help fix' for details.

Mendukung folder, nama file, direktori sebagai parameter, menerima flag -fix untuk mengirim parameter untuk menunjukkan modifikasi apa yang akan dilakukan, dapat melihat nilai yang tersedia melalui perintah got tool fix -help

sh
$ 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.

Berikut adalah contoh, kode sumber menggunakan paket golang.org/x/net/context

sh
package main

import (
  "fmt"
  "golang.org/x/net/context"
)

func main() {
  background := context.Background()
  fmt.Println(background.Err())
}

Gunakan go fix untuk memperbaiki, ganti dengan paket context di library standar, kita dapat menggunakan perintah berikut untuk mengganti

sh
$ go fix -fix context main.go

Juga dapat tidak mengganti, lihat perubahan file sebelum dan sesudah.

sh
$ 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() {

Bahasa go sudah lahir lebih dari sepuluh tahun hanya memiliki sembilan parameter pengganti yang tersedia, dapat dilihat kompatibilitas dijaga cukup baik.

fmt

fmt adalah alat pemformatan bawaan bahasa go, digunakan untuk memformat file kode sumber go.

sh
$ go fmt -h
usage: go fmt [-n] [-x] [packages]
Run 'go help fmt' for details.

Lihat dokumentasi detailnya melalui perintah go doc gofmt

sh
$ 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 menggunakan tab untuk indentasi, spasi untuk alignment, secara default kode yang diformat akan ditampilkan di output standar, bukan menimpa file asli. Perintah go fmt sebenarnya menggunakan perintah gofmt, ini adalah file biner independen, berada di direktori GOROOT/bin.

sh
$ ls $GOROOT/bin -1
go.exe*
gofmt.exe*

Tambahkan flag -n ke perintah go fmt dapat mengetahui instruksi yang akan dieksekusi.

sh
$ go fmt main.go
/golang/bin/gofmt.exe -l -w main.go

Dapat melihat go fmt sebenarnya adalah alias dari gofmt -l -w, perintah gofmt memiliki parameter berikut

  • -d: Tampilkan perbedaan file sebelum dan sesudah pemformatan
  • -e: Tampilkan semua error
  • -l: Tampilkan nama file yang berubah
  • -r: Terapkan aturan pemformatan
  • -s: Coba sederhanakan kode
  • -w: Timpa file sumber, jika terjadi error kembalikan backup

Misalnya sekarang ada file sumber berikut

go
$ cat main.go
package main

import "fmt"

func main() {
fmt.Println("hello world!")}

Melalui parameter -d dapat melihat preview perubahannya

sh
$ 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!")
+}

Parameter -l akan menampilkan nama file yang akan dimodifikasi

$ gofmt -l .
main.go

Jika ada error syntax, parameter -e dapat menampilkan lebih detail

sh
$ 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 akan menerapkan modifikasi ke file sumber

sh
$ gofmt -l -w .
main.go

$ cat main.go
package main

import "fmt"

func main() {
        fmt.Println("hello world!")
}

Anda dapat menemukan sebagai alat pemformatan, gofmt sama sekali tidak menyediakan konfigurasi kustom apa pun, sedangkan formatter prettify yang khusus untuk mempercantik kode js menyediakan banyak konfigurasi untuk memformat kode, di sini dapat mencerminkan sikap resmi go, jangan berpikir untuk melakukan personalisasi apa pun, kode semua orang sebaiknya konsisten, setidaknya ada satu keuntungan yaitu saat membaca kode tidak perlu beradaptasi dengan kebiasaan orang lain. Namun sebenarnya masih menyimpan satu item kustom, yaitu aturan pengganti kode yang diformat, aturan dapat dikustomisasi, formatnya adalah sebagai berikut

pattern -> replacement

Misalnya menghapus kurung yang redundan

(a) -> a

Lihat perubahan file

sh
$ 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!")
 }

Dapat melihat gofmt akan menghapus kurung yang redundan.

get

Perintah get pasti yang paling sering digunakan selama pengembangan go, fungsinya adalah mengunduh kode sumber paket alamat yang ditentukan ke direktori yang sesuai dengan GOMODCACHE.

sh
$ go get -h
usage: go get [-t] [-u] [-v] [build flags] [packages]
Run 'go help get' for details.
  • -u: Coba perbarui versi minor dan patch paket, jika melibatkan perubahan versi utama, seperti v1->v2, tidak akan diperbarui.
  • -t: Perbarui versi dependensi dalam testing
  • -v: Tampilkan paket yang dikompilasi, sebenarnya merupakan salah satu parameter build flags

Di masa lalu, fungsi go get mirip dengan go install, akan mengunduh dan mengkompilasi paket-paket ini, namun dengan lahir dan penyempurnaan modul go, fungsi ini secara bertahap ditinggalkan, perintah get sekarang yang paling sering digunakan adalah untuk mengunduh dan mengurai dependensi untuk modul go, jadi Anda dapat melihat perintah go get juga mendukung flag build jenis ini, dan jika Anda mencoba menggunakan go get di luar modul seperti menggunakan go install, akan memberi tahu Anda bahwa penggunaan ini sudah dihapus.

sh
$ 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'.

Adapun mengapa masih mempertahankan ini dalam deskripsi dokumentasi juga tidak diketahui, melihat kode sumber perintah get, Anda masih akan menemukan flag-flag lama yang dipertahankan.

go
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
)

Kembali ke topik utama, perintah get akan mengunduh kode sumber paket yang ditentukan ke direktori dependensi global lokal, yaitu direktori yang sesuai dengan GOCACHE, kemudian mencatat informasi ke file go.mod dan go.sum, yang pertama bertanggung jawab untuk mencatat versi, yang后者 bertanggung jawab untuk mencatat checksum sha1 untuk memastikan keamanan. Perintah get sebenarnya berbasis VCS, yaitu sistem kontrol versi lokal,总共 mendukung beberapa berikut

  • git
  • hg (Mercurial)
  • bzr (Bazaar)
  • svn
  • fossil

Di antaranya, default hanya mendukung git dan hg, dapat dikonfigurasi di GOVCS, formatnya adalah sebagai berikut

GOVCS=github.com:git,example.com:hg,*:git|hg,*:all

GOVCS hanya mendukung git dan hg sebagai VCS, tiga lainnya perlu dikonfigurasi di GOPRIVATE.

Perintah go get总共 memiliki beberapa cara penggunaan berikut, dapat langsung menggunakan alamat dependensi sebagai parameter

sh
$ go get golang.org/x/net

Juga dapat menentukan versi

sh
$ go get golang.org/x/net@0.17.0

Tentukan versi terbaru

sh
$ go get golang.org/x/net@latest

Coba perbarui versi

sh
$ go get -u golang.org/x/net

Hapus dependensi tertentu

sh
$ go get golang.org/x/net@none

Di atas ini digunakan untuk mengelola dependensi biasa, juga dapat digunakan untuk mengelola dependensi yang tidak begitu biasa, misalnya memperbarui versi bahasa go

sh
$ 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

Bahkan juga dapat digunakan untuk memperbarui versi toolchain go

sh
$ go get toolchain@latest

Ketika Anda menggunakan go get untuk memperbarui versi go dan toolchain, mereka akan menginstal versi go baru di direktori GOMODCACHE/golang.org/

sh
$ ls $(go env GOMODCACHE)/golang.org -1
'toolchain@v0.0.1-go1.21.3.windows-amd64'/
x/

Saat ini kemudian modifikasi GOROOT secara manual dapat beralih ke versi yang ditentukan.

install

Perintah install mirip dengan perintah get, keduanya digunakan untuk mengunduh dependensi pihak ketiga, tetapi perbedaannya adalah perintah get mengunduh kode sumber, sedangkan perintah install akan mengkompilasi kode sumber menjadi file biner yang dapat dieksekusi oleh mesin ini, path penyimpanan file biner pertama-tama di direktori GOBIN, kedua di GOPATH/bin. Fungsi utama perintah ini adalah untuk mengunduh beberapa alat command line publik pihak ketiga, berkat kecepatan kompilasi dan portabilitas bahasa go, tidak perlu mengunduh file biner, tetapi langsung mengunduh kode sumber kemudian mengkompilasi di lokal.

sh
$ go install -h
usage: go install [build flags] [packages]
Run 'go help install' for details.

Perintah install menerima flag build dan nama paket sebagai parameter, dalam kasus gomod diaktifkan, nama paket harus membawa nomor versi. Misalnya mengunduh debugger delve

sh
$ 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/

Pertama-tama akan mengunduh kode sumber ke path yang disimpan di GOMODCACHE, ini sama dengan perintah get, kemudian beralih ke direktori kerja sementara, mengkompilasinya, setelah kompilasi selesai memindahkan file biner ke direktori GOPATH/bin, terakhir menghapus folder sementara. Perintah install juga memiliki batasan yaitu paket yang diunduh harus merupakan paket entry proyek tersebut, artinya harus berisi file entry main.go, jika tidak akan memberi tahu Anda tidak dapat menginstal. Misalnya, gunakan go install untuk mengunduh gin

sh
$ 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 package

gin adalah library dependensi framework web, bukan alat command line, tentu saja tidak ada file entry, jadi juga akan gagal instalasi.

list

Perintah list akan menampilkan paket di lokasi yang ditentukan, satu baris per paket, dan mendukung output yang diformat kustom, mendukung banyak parameter, prasyarat penggunaannya adalah harus dalam proyek yang mendukung gomod.

sh
$ go list -h
usage: go list [-f format] [-json] [-m] [list flags] [build flags] [packages]
Run 'go help list' for details.

Parameter yang didukung adalah sebagai berikut

  • -f: Parameter pemformatan
  • -json: Output format json
  • -compiled: Tampilkan semua paket yang akan dikompilasi oleh kompiler
  • -deps: Tampilkan nama setiap paket dan setiap paket yang dependensinya
  • -test: Tampilkan paket testing setiap paket
  • -e: Output normal saat bertemu paket error
  • -find: Jangan uraikan hubungan dependensi paket-paket ini
  • -export: Saat menggunakan parameter ini, atur nilai field Package.Export struct ke file yang berisi informasi ekspor paket yang ditentukan terbaru, dan atur nilai field Package.BuildID ke BuildID paket, terutama untuk output yang diformat.

Parameter informasi modul,

  • -m: Tampilkan modul bukan output paket

  • -versions: Tampilkan semua informasi yang tersedia untuk modul

  • -retracted: Tampilkan versi yang ditarik dari modul

Parameter [packages] dapat berupa nama paket yang ditentukan, atau folder, juga dapat all, menunjukkan di mana saja, saat menggunakan parameter -m, all menunjukkan semua dependensi yang direferensikan oleh modul saat ini.

Misalnya, file saat ini hanya memiliki satu file main.go, dan hanya memiliki satu baris kode output "hello world", setelah menjalankan go list -deps ., menampilkan dari proyek saat ini ke fmt dan semua paket dependensi yang direferensikannya.

bash
$ 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

Atau output semua dependensi modul di bawah proyek saat ini

bash
$ 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

Output perintah list adalah per baris, setiap baris output adalah satu paket. Resmi menyediakan parameter -f untuk kita mengustomisasi format output baris, nilai yang diterimanya adalah syntax template yang didefinisikan oleh paket engine template template/text, misalnya contoh berikut

sh
-f "package {{ .Dir }} {{ .Name }}"

Setiap paket yang diiterasi akan dimasukkan sebagai struct berikut, semua field dalam struct ini dapat digunakan sebagai parameter template.

go
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
}

Jika mengiterasi modul, akan dimasukkan sebagai struct berikut, semua field-nya juga dapat digunakan sebagai parameter template.

go
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
}

Lihat semua paket

bash
$ 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

Lihat modul

bash
$ go list -m -f "mod {{.Path}} {{.Version}} {{.GoVersion}} {{.GoMod}}"
mod golearn  1.21.3 /golearn/go.mod

mod

go mod adalah perintah khusus untuk mengelola modul go.

sh
$ 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.

Memiliki beberapa sub-perintah berikut

  • download: Unduh semua dependensi yang tercantum dalam file go.mod ke cache lokal
  • edit: Edit file go.mod, antarmuka baris perintah yang disediakannya terutama disediakan untuk dipanggil oleh alat atau skrip lain.
  • init: Inisialisasi proyek gomod di direktori saat ini
  • tidy: Unduh dependensi yang hilang, hapus dependensi yang tidak digunakan
  • graph: Output grafik dependensi
  • verify: Verifikasi dependensi lokal
  • why: Jelaskan mengapa bergantung pada modul-modul ini
  • vendor: Ekspor dependensi proyek ke direktori vendor

init

sh
$ go help mod init
usage: go mod init [module-path]

Perintah init digunakan untuk menginisialisasi proyek gomod, satu-satunya parameter adalah path modul, di masa depan jika orang lain ingin mengunduh dependensi Anda perlu menggunakan path modul ini sebagai dasar. Aturan penamaannya umumnya adalah

domain_name/user_name/repo_name

Misalnya umumnya semua orang akan menempatkan proyek di github, jadi dapat

github.com/jack/gotour

Tidak terlalu direkomendasikan menggunakan simbol khusus sebagai path modul. Lihat contoh penggunaan

sh
$ mkdir gotour

$ cd gotour

$ go mod init "github.com/jack/gotour"
go: creating new go.mod: module github.com/jack/gotour

tidy

$ go help mod tidy
usage: go mod tidy [-e] [-v] [-x] [-go=version] [-compat=version]

Perintah tidy akan menghapus item dependensi yang tidak berguna di go.mod, yaitu item dependensi yang tidak direferensikan, serta akan mengunduh item dependensi yang direferensikan tetapi tidak ada. Mendukung parameter berikut

  • -v, output modul dependensi yang dihapus
  • -e, abaikan error jika terjadi selama proses dan lanjutkan eksekusi
  • -x, output proses eksekusi
  • -go=version, perbarui versi go di file go.mod
  • -compact=version, pertahankan checksum tambahan apa pun yang diperlukan dari versi Go utama yang ditentukan untuk berhasil memuat grafik modul, dan jika perintah go versi ini memuat paket yang diimpor apa pun dari versi modul yang berbeda, akan menyebabkan tidy error. Parameter ini umumnya jarang digunakan, umumnya hanya akan error saat perubahan versi, dapat pergi ke stackoverflow lihat jawaban ini go modules - go mod tidy error message: "but go 1.16 would select" - Stack Overflow

Lihat contoh penggunaan

sh
$ 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

sh
$ go help mod download
usage: go mod download [-x] [-json] [-reuse=old.json] [modules]

Meskipun nama perintah download diterjemahkan sebagai unduh, tetapi hanya mengunduh dependensi ke cache dependensi lokal, tidak akan memodifikasi file go.mod, fungsinya adalah pre-download dependensi ke cache file lokal, jika ingin mengunduh dependensi tertentu, direkomendasikan menggunakan go get atau go mod tidy.

Berikut adalah beberapa contoh penggunaan

sh
$ 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)

Jika tanpa parameter apa pun, akan mengunduh semua dependensi yang ada di file go.mod tetapi tidak ada di cache dependensi lokal, jika tidak ada yang perlu diunduh akan output

go: no module dependencies to download

edit

sh
$ go help mod edit
usage: go mod edit [editing flags] [-fmt|-print|-json] [go.mod]

edit adalah antarmuka baris perintah, digunakan untuk memodifikasi file go.mod, umumnya disediakan untuk program lain digunakan, beberapa editor IDE untuk menyediakan dukungan gomod akan menggunakan perintah-perintah ini. Mendukung parameter berikut

  • -module, ubah path modul
  • -go=version, ubah versi go yang diharapkan
  • -require=path@version, tambahkan item dependensi
  • -droprequire=path@version, hapus item dependensi
  • -exclude=path@version, tambahkan item dependensi yang dikecualikan
  • -dropexclude=path@version, hapus item dependensi yang dikecualikan
  • -replace=old@version=new@version, tambahkan item dependensi pengganti
  • -dropreplace=old@version, hapus item dependensi pengganti
  • -retract=version, tambahkan item rollback versi
  • -dropretract=version, hapus item rollback versi

Beberapa parameter lain untuk tampilan

  • -print, output konten file
  • -json, output dalam format json

Misalnya contoh di bawah ini

$ 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

sh
$ go help mod graph
usage: go mod graph [-go=version] [-x]

Perintah graph akan output grafik dependensi di bawah proyek saat ini, readability-nya sangat buruk, dan sebagian besar waktu bukan untuk dibaca manusia, hasilnya biasanya akan diproses kemudian ditampilkan dalam bentuk visual. Setiap baris adalah satu dependensi, formatnya adalah sebagai berikut

引用方 被引用方

Misalnya

golearn go@1.21.3

Juga mendukung dua parameter

  • -go=version, gunakan versi go yang diberikan untuk memuat grafik dependensi, nilainya tidak boleh kurang dari versi di file go.mod.
  • -x, tampilkan perintah yang dieksekusi selama proses.

Lihat contoh penggunaan sederhana

sh
$ 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

sh
$ go help mod vendor
usage: go mod vendor [-e] [-v] [-o outdir]

vendor adalah solusi alternatif gopath sebelum gomod diluncurkan, setiap proyek go akan memiliki direktori vendor, menyimpan dependensi setiap proyek secara terpisah sesuai dengan format domain/user/project, seperti node_module yang gemuk di sebelah NodeJs setiap proyek dependensi disimpan terpisah, cara manajemen dependensi ini sekarang terlihat memang sangat bodoh, tetapi pada saat itu memang tidak ada solusi yang lebih baik, alasan mempertahankan vendor adalah karena go menganut janji kompatibilitas ke bawah, beberapa proyek lama termasuk kode sumber go mungkin masih menggunakan vendor.

Kembali ke topik utama, vendor adalah sub-perintah go mod, dapat mengekspor dependensi global yang direferensikan oleh modul saat ini ke direktori vendor.

sh
$ go mod vendor -h
usage: go mod vendor [-e] [-v] [-o outdir]
Run 'go help mod vendor' for details.

Memiliki beberapa parameter berikut

  • -o: Tentukan path folder output
  • -v: Output setiap dependensi
  • -e: Jangan keluar saat terjadi error tetap lanjutkan

Lihat contoh di bawah ini, pertama gunakan go list -m all untuk melihat dependensi yang direferensikan oleh proyek saat ini

sh
$ 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

Ekspor ke direktori vendor saat ini

sh
$ 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

Struktur direktori setelah ekspor adalah sebagai berikut

└─vendor
    ├─github.com
    │  ├─davecgh
    │  │  └─go-spew
    │  │      └─spew
    │  ├─pkg
    │  │  └─errors
    │  ├─pmezard
    │  │  └─go-difflib
    │  │      └─difflib
    │  └─stretchr
    │      └─testify
    │          └─assert
    └─gopkg.in
    |    └─yaml.v3
    |
    |--modules.txt

Di antaranya modules.txt adalah file yang mendeskripsikan semua item dependensi, mirip dengan go.mod saat ini.

verify

sh
$ go help mod verify
usage: go mod verify

Perintah ini akan memeriksa apakah dependensi proyek telah dimodifikasi sejak diunduh ke lokal. Misalnya, jika tidak ada masalah akan output all modules verified

sh
$ go mod verify
all modules verified

Jika tidak akan melaporkan di mana terjadi perubahan, dan mengakhiri perintah dengan status tidak normal. Misalnya

sh
$ 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...

Jelaskan mengapa paket ini bergantung, sebenarnya adalah output grafik dependensi terkait. Misalnya

sh
$ go mod why gorm.io/gorm
# gorm.io/gorm
golearn
gorm.io/gorm

Secara default hanya akan mengurai impor dari main, tambahkan parameter -m dapat menganalisis situasi impor setiap paket.

work

Perintah work adalah alat pengembangan lokal untuk manajemen multi-modul go

bash
$ 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

Sub-perintah init digunakan untuk menginisialisasi workspace, perintah ini akan membuat file bernama go.work

bash
$ go work init -h
usage: go work init [moddirs]
Run 'go help work init' for details.

Terima parameter [moddirs] untuk menentukan modul mana yang akan dimasukkan ke dalam manajemen, misalnya

bash
$ go work init ./service ./api

use

Sub-perintah use digunakan untuk menambahkan direktori modul yang dikelola ke go.work

bash
$ 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.

Terima [moddirs] sebagai parameter, ada -r yang menunjukkan pencarian rekursif modul di path [moddirs], misalnya

bash
$ go work use -r ./oss-api ./multi_modules

edit

Fungsi sub-perintah edit sama dengan go mod edit, keduanya disediakan untuk antarmuka baris perintah untuk alat dan skrip lain beroperasi.

$ 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

Parameter adalah sebagai berikut

  • -fmt, format file go.work

  • -use, -dropuse, tambahkan dan hapus path modul

  • -replace=old[@v]=new[@v], -dropreplace=old[@v]=new[@v], digunakan untuk menambahkan dan menghapus modul yang akan diganti

  • -go, -toolchain=name, tentukan versi go, dan tentukan toolchain yang akan digunakan

  • -print, cetak modifikasi terakhir, tidak tulis kembali ke file

  • -json, output dalam format json, tidak dapat digunakan bersama dengan -print, struktur tipe yang sesuai adalah sebagai berikut

    go
    type 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
    }

Beberapa contoh penggunaan adalah sebagai berikut, output format

bash
$ go work edit -fmt -print
go 1.22.0

use (
        ./ab/cd
        ./auth
        ./user
)

Output json

bash
$ go work edit -fmt -json
{
        "Go": "1.22.0",
        "Use": [
                {
                        "DiskPath": "./ab/cd"
                },
                {
                        "DiskPath": "./auth"
                },
                {
                        "DiskPath": "./user"
                }
        ],
        "Replace": null
}

sync

Sub-perintah sync digunakan untuk mengembalikan daftar modul di go.work ke masing-masing modul di workspace.

bash
$ go help work sync
usage: go work sync

Sync syncs the workspace's build list back to the
workspace's modules

Proses ini terutama terjadi setelah pengembangan lokal selesai, setiap modul telah menyelesaikan pekerjaan rilis, saat ini menggunakan sync, akan memperbarui dependensi di go.mod semua modul worksapce berdasarkan hubungan dependensi masing-masing modul, sehingga tidak perlu kita memperbarui secara manual.

vendor

Perintah vendor akan membuat salinan semua library dependensi modul di workspace ke direktori vendor.

bash
$ go work help vendor
usage: go work vendor [-e] [-v] [-o outdir]

Fungsi sama dengan go mod vendor, tidak akan dijelaskan terlalu banyak.

vet

Perintah vet adalah alat pemeriksaan error statis kode sumber bahasa go, seperti alat lint bahasa lain, misalnya Eslint.

sh
$ 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.

Pertama lihat contoh sederhana, sekarang ada kode sumber berikut

sh
$ cat main.go
package main

import "fmt"

func main(){
        fmt.Println("hello world!"
}

Jalankan go vet tanpa parameter apa pun di direktori tingkat yang sama

sh
$ go vet
vet: ./main.go:6:28: missing ',' before newline in argument list (and 1 more errors)

vet akan melaporkan file mana baris mana出了什么问题。Mendukung flag build sebagai parameter, misalnya -n dan -x, mendukung paket, folder, nama file sebagai parameter.

sh
$ go vet .
$ go vet main.go
$ go vet ./cmd
$ go vet runtime

Lihat parameter dan penjelasan lebih detail melalui perintah berikut.

sh
$ 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
    ......

Perintah go tool vet tidak dapat langsung digunakan untuk memeriksa kode, harus menggunakan go vet. [vet flag] di parameter go vet mendukung pengaturan analyzer kode, nilai yang tersedia adalah sebagai berikut

asmdecl      Periksa apakah file assembly cocok dengan deklarasi go
assign       Periksa apakah ada variabel yang tidak berguna
atomic       Periksa apakah merusak atomisitas saat menggunakan sync/atomic
bools        Periksa apakah salah menggunakan operator logika
buildtag     Periksa build tag
cgocall      Periksa perilaku yang melanggar aturan passing pointer cgao
composites   Periksa复合结构 yang tidak diinisialisasi, seperti map, chan
copylocks    Periksa apakah terjadi penyalinan nilai lock
directive    Periksa perintah toolchain go
errorsas     Periksa apakah mengirim tipe non-pointer atau non-error ke errors.As
framepointer Periksa apakah assembly yang dioptimalkan kompilasi menghapus frame pointer sebelum menyimpannya
httpresponse Periksa apakah salah menggunakan httpresponse
ifaceassert  Periksa type assertion dari interface ke interface
loopclosure  Masalah referensi variabel loop
lostcancel   context.WithCancel tidak menggunakan fungsi cancel
nilfunc      Periksa apakah ada perbandingan yang tidak berguna antara fungsi dan nil
printf       Periksa apakah parameter pemformatan printf benar
shift        Periksa apakah ada shift yang sama dengan atau melebihi lebar integer
sigchanyzer  Periksa chan os.Signal yang tidak buffered
slog         Periksa panggilan log terstruktur yang tidak sah
stdmethods   Periksa apakah signature metode interface yang diketahui benar
stringintconv Periksa konversi string integer
structtag    Periksa apakah tag struct benar
testinggoroutine Periksa apakah menggunakan goroutine untuk memanggil testing.Fatal dalam testing
tests        Periksa penggunaan umum error dalam testing dan contoh
timeformat   Periksa apakah format waktu yang digunakan oleh (time.Time).Format atau time.Parse benar
unmarshal    Periksa apakah mengirim tipe non-pointer atau non-interface ke unmarshal
unreachable  Periksa kode yang tidak dapat dijangkau
unsafeptr    Periksa konversi uintptr ke unsafe.Pointer yang tidak benar
unusedresult Periksa nilai return fungsi yang tidak digunakan

Semua ini adalah analyzer yang menganalisis titik tertentu, misalnya analyzer timeformat memeriksa apakah panggilan time.Format sesuai dengan syntax yang benar. Secara default semua analyzer di atas akan diaktifkan, aktifkan secara terpisah dapat menggunakan format berikut

sh
$ go vet -timeformat main.go

Nonaktifkan secara terpisah

sh
$ go vet -timeformat=false main.go

Kode sumber analyzer ini berada di cmd/vendor/golang.org/x/tools/go/analysis/passes, setiap analyzer adalah satu perangkap yang mudah dilakukan oleh bahasa go, jadi sangat direkomendasikan menggunakan perintah vet untuk memeriksa kode Anda. Selain ini, juga mendukung beberapa flag parameter lain

  • -V, hanya cetak versi lalu keluar
  • -json, output dalam format json
  • -c=n, tampilkan jumlah baris konflik dalam konteks (sepertinya tidak ada efek apa pun)

Juga ada beberapa analyzer eksternal, misalnya shadows, bertanggung jawab untuk mendeteksi masalah variable hiding dari penamaan variabel pendek, karena eksternal jadi perlu menggunakan go install untuk mengunduh

sh
$ go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latest

Format penggunaan adalah sebagai berikut

sh
$ go vet -vettool=$(which shadow)

test

sh
$ 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.

Perintah test adalah perintah yang menyediakan fungsi testing dalam toolchain bahasa go, fungsi ini cukup penting, untuk sebuah software而言, testing yang lengkap adalah hal yang sangat diperlukan. Di sini hanya简单介绍 bagaimana menggunakan perintah test, jika ingin mempelajari lebih banyak tentang testing, kunjungi: Testing

Selain mendukung parameter kompilasi perintah build, test juga mendukung beberapa parameter berikut

  • -args, parameter entry program
  • -c, kompilasi file biner testing paket saat ini ke direktori saat ini tetapi tidak mengeksekusi, beri nama dengan cara pkg.test
  • -exec, jalankan beberapa perintah lain sebelum testing dimulai
  • -json, gaya output testing menjadi json
  • -o, tentukan path name file biner testing

Juga mendukung banyak testflag, gunakan perintah help untuk melihat semua testflag

sh
$ go help testflag
`go test` 命令既接受作用于 `go test` 本身的标志,
也接受作用于生成的测试二进制文件的标志。

`go test` 命令识别以下标志,并用于控制任何测试的执行:
        -bench regexp
        -benchtime t
        -count n
    ......

Perkenalkan beberapa yang umum digunakan

  • -v, output hasil testing setiap use case.
  • -timeout duration, waktu timeout eksekusi testing
  • -skip regexp, lewati use case testing yang ditentukan
  • -short, persingkat waktu running untuk use case testing yang memakan waktu lama
  • -shuffle, acak urutan eksekusi semua use case testing
  • -run regexp, jalankan use case testing yang ditentukan
  • -list regexp, daftar setiap use case testing
  • -cpu 1,2,4, tentukan jumlah cpu
  • -count n, tentukan berapa kali setiap use case testing dieksekusi

Penggunaan paling sederhana adalah, tanpa parameter apa pun, akan mengeksekusi semua use case testing di bawah paket saat ini, dan output hasilnya.

sh
$ ls *_test.go
hello_test.go

$ go test
PASS
ok      golearn 0.522s

Tentukan file testing tertentu

sh
$ go test hello_test.go
ok      command-line-arguments  0.041s

Tambahkan parameter -v dapat melihat output yang lebih detail, ini cukup sering digunakan.

sh
$ 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

Tentukan use case testing tertentu

sh
$ go test -v -run TestHello
=== RUN   TestHello
    hello_test.go:6: hello world!
--- PASS: TestHello (0.00s)
PASS
ok      golearn 0.028s

Saat testing, perintah test memiliki dua mode, pertama-tama bahas mode folder, ketika menjalankan perintah test tanpa parameter package, akan menjalankan testing dengan mode folder, misalnya beberapa perintah di bawah ini

sh
$ go test
$ go test -v

Dalam mode ini, nonaktifkan cache testing. Mode lainnya adalah mode list, ketika parameter package tidak kosong, akan menjalankan testing dengan mode list, perbedaannya dengan yang前者 adalah apakah mengaktifkan cache testing. Misalnya beberapa di bawah ini

sh
$ go test -v .
$ go test -v ./...
$ go test .
$ go test -v net/http

Dalam mode list, go akan mengkompilasi setiap file testing di bawah paket yang ditentukan menjadi file biner dan mengeksekusinya, untuk menghindari running testing berulang, go secara default akan meng-cache hasilnya, tidak akan mengkompilasi ulang saat running kedua kali. Gunakan parameter berikut akan secara default mengaktifkan cache

  • -benchtime
  • -cpu
  • -list
  • -parallel
  • -run
  • short
  • -timeout
  • -failfast
  • -v

Gunakan parameter lain selain parameter ini dapat menonaktifkan cache, metode yang direkomendasikan resmi adalah menggunakan -count=1 untuk menonaktifkan cache. Misalnya

sh
$ go test -v -count=1 ./...

Instruksi

Berbeda dengan perintah, instruksi go ada dalam file sumber dalam bentuk hard-coded, mereka memiliki nama lain yang lebih terminologis: compiler directives (pragma directives).

Compiler dan linker akan mengubah perilaku mereka sendiri karena mereka sehingga mencapai efek kontrol kompilasi, sedikit mirip dengan macro dalam bahasa c, tentu saja tidak semua instruksi digunakan untuk mempengaruhi kompilasi, sebagian digunakan untuk perilaku fungsional lain, misalnya instruksi generate umumnya digunakan untuk fungsi pembuatan kode. Instruksi ini umumnya ada dalam bentuk komentar, dan menggunakan //go: sebagai prefix, di antaranya tidak boleh berisi spasi apa pun, misalnya instruksi //go:generate. Semua jenis instruksi总共 dibagi menjadi dua

  • Instruksi fungsional, ini adalah instruksi fungsional yang disediakan oleh go dapat digunakan secara bebas, seperti generate, embed, build.
  • Instruksi compiler, jenis instruksi ini perlu digunakan dengan hati-hati, penggunaan sembarangan dapat menyebabkan hasil yang tidak dapat diprediksi.

Selain instruksi fungsional, sebagian besar instruksi hanya dapat bertindak pada signature fungsi. Untuk instruksi compiler dapat menjalankan perintah go doc compile untuk melihat instruksinya. Untuk semua instruksi, dapat menemukan informasi terkait mereka di cmd/compile/internal/ir/node.go: 440.

generate

sh
$ go help generate
usage: go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]

Instruksi generate sesuai namanya adalah terkait pembuatan, umumnya fungsinya adalah untuk menjalankan perintah yang akan menghasilkan kode dan memperbarui kode sumber, tetapi sebenarnya dapat menjalankan perintah apa pun. Dan, instruksi generate berbeda dengan instruksi lain, memiliki perintah khusus yang dapat digunakan untuk menjalankan semua instruksi generate yang berada di file sumber. Dapat menggunakan nama file atau nama paket sebagai parameter input untuk menunjukkan file mana yang akan menjalankan instruksi generate, berikut adalah parameter lainnya.

  • -run=regex, jalankan instruksi generate yang ditentukan
  • -skip=regex, lewati instruksi generate yang ditentukan
  • -n, cetak perintah yang akan dieksekusi
  • -x, cetak perintah yang dieksekusi selama proses
  • -v, output file yang diproses

Selain itu, perintah yang dieksekusi dalam instruksi generate juga mendukung beberapa parameter built-in berikut

  • $GOARCH, arsitektur cpu
  • $GOOS, sistem operasi
  • $GOFILE, nama file
  • $GOLINE, nomor baris
  • $GOPACKAGE, nama paket
  • $GOROOT, go root
  • $DOLLAR, simbol dolar
  • $PATH, variabel lingkungan path

Lihat contoh, tidak ada kode apa pun hanya satu baris komentar

go
package main

//go:generate echo "hello world!"

Jalankan perintah

$ go generate .
hello world!

Contoh ini adalah menjalankan perintah go

go
package main

//go:generate go version

Jalankan perintah

sh
$ go generate .
go version go1.21.3 windows/amd64

Instruksi generate dapat digunakan untuk menjalankan perintah apa pun, misalnya swagger menghasilkan dokumentasi API, atau Wire menghasilkan kode IOC. Namun instruksi ini tidak cocok untuk menjalankan perintah yang terlalu kompleks, cocok untuk menjalankan perintah singkat, jika ada kebutuhan kompleks dapat menggunakan skrip atau makefile sebagai pengganti.

embed

Instruksi embed adalah baru di 1.16, fungsinya adalah dapat mengemas file statis bersama ke dalam file biner, misalnya template HTML之类的。Formatnya adalah sebagai berikut

go
//go:embed pattern

pattern dapat berupa ekspresi glob, juga dapat berupa folder atau file tertentu. Lihat contoh

go
package main

import "embed"

//go:embed *
var static embed.FS

Instruksi embed mengharuskan berada di atas variabel global dengan tipe embed.Fs, perhatikan harus variabel global, dan menggunakannya harus mengimpor paket embed, dalam contoh ini, * mewakili akan mengemas semua file di bawah folder saat ini ke dalam file biner, tetapi tidak akan mengizinkan folder yang dimulai dengan ..

Contoh di bawah ini menunjukkan membaca konten dari file yang disematkan

go
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))
}

Hanya memiliki tiga metode, penggunaannya tidak berbeda dengan sistem file biasa, dan karena mengimplementasikan antarmuka io/Fs, juga dapat diteruskan sebagai objek Fs.

go
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)

Contoh di bawah ini menunjukkan menyematkan file html melalui instruksi embed, dan mengakses melalui layanan http.

go
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)
}

Hasil akses adalah sebagai berikut

sh
$ 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>

Instruksi embed juga mendukung tipe variabel global dapat berupa []byte, misalnya contoh di bawah ini

go
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)
}

Efek yang diimplementasikan tidak jauh berbeda dengan contoh sebelumnya.

sh
$ 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

Di bagian build-Kontrol Kompilasi, dibahas menggunakan instruksi // +build untuk mengontrol perilaku kompilasi. Sedangkan instruksi //go:build adalah baru di 1.17, dimaksudkan untuk menggantikan instruksi sebelumnya, tetapi sekarang sudah 1.21 juga belum menggantikan, diperkirakan akan ada dalam bentuk koeksistensi di masa depan, tentang instruksi baru ini, dokumentasi resmi juga memiliki pengenalan: build constraints. Fungsinya tidak berbeda dengan yang前者, tetapi syntax lebih ketat, mendukung ekspresi boolean, lihat contoh

go
//go:build (linux && 386) || (darwin && !cgo)

package pkg_name

Cara ini readability jauh lebih tinggi daripada yang asli.

line

Instruksi line akan mempengaruhi nomor baris, nomor kolom, dan nama file baris berikutnya, fungsinya hanya ini, sebagian besar waktu mungkin digunakan untuk debug error之类的。Misalnya saat terjadi error, akan mengubah informasi output compiler.

go
package main

var a undefinedType

func main() {

}

Secara normal, compiler akan output

.\main.go:3:7: undefined: undefinedType

Tetapi jika menggunakan instruksi line, akan berbeda

go
package main

//line abc.go:10:100
var a undefinedType

func main() {

}

Maka outputnya adalah

abc.go:10:106: undefined: undefinedType

Dan karena alasan warisan sejarah, instruksi line juga merupakan satu-satunya instruksi yang penggunaannya berbeda dengan instruksi lain. Formatnya adalah

go
//line filename:line:column

Dapat melihat tidak memerlukan go: sebagai prefix.

linkname

Operasi instruksi ini dapat digunakan untuk linking fungsi atau variabel global paket lain, bahkan jika itu adalah tipe privat, operasi ini sering muncul di library standar terutama runtime, beberapa fungsi tidak memiliki body fungsi diimplementasikan melalui cara ini, bagian lain dari fungsi body kosong diimplementasikan oleh assembly. Lihat penggunaannya, format penggunaan adalah sebagai berikut

go
//go:linkname nama_tipe_link tipe_yang_di-link

Dan sebelum menggunakannya, misalnya mengimpor paket unsafe. Lihat contoh sederhana linking tipe privat di library standar

go
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")))
}

Output

15395306441938000233

Ini menghubungkan fungsi privat runtime.memhash dengan fungsi yang kami deklarasikan sendiri, fungsi ini tidak memiliki body fungsi hanya signature, hanya berfungsi sebagai carrier. Fungsi memhash adalah给定 pointer, seed hash, dan offset memori, menghitung hash berdasarkan memori. Proses linking ini selesai selama kompilasi,

Jika bukan library standar, maka situasinya agak berbeda, misalnya di paket example ada fungsi test, sebelum linking pertama-tama harus mengimpor paket ini secara anonim.

go
package example

// 一个私有类型,外界无法访问。
func test() string {
  return "a"
}
go
package main

import (
  "fmt"
  _ "golearn/example"
  _ "unsafe"
)

//go:linkname test golearn/example.test
func test() string

func main() {
  fmt.Println(test())
}

Output

a

Dapat melihat sudah berhasil linking, metode ini dapat melewati sistem modul go untuk melakukan apa saja, tetapi tidak direkomendasikan untuk digunakan secara besar-besaran, kecuali Anda tahu apa yang Anda lakukan.

noinline

Instruksi noinline menunjukkan satu fungsi dilarang optimasi inline, bahkan jika sangat sederhana. Lihat contoh sederhana

go
package main

func val() string {
  return "val"
}

func main() {
  var c = val()
  _ = c
}

val adalah fungsi yang sangat sederhana, fungsinya adalah mengembalikan literal string, karena terlalu sederhana dan hasilnya selalu dapat diprediksi, maka saat kompilasi akan dioptimalkan oleh compiler menjadi bentuk berikut

go
package main

func main() {
  var c = "val"
  _ = c
}

Lihat seperti apa assembly-nya, dapat melihat tidak ditemukan panggilan fungsi 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

Selanjutnya tambahkan instruksi noinline

go
package main

//go:noinline
func val() string {
  return "val"
}

func main() {
  var c = val()
  _ = c
}

Lihat lagi bentuk assembly-nya

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

Kali ini dapat melihat dengan sangat jelas panggilan main.val ini, dan ini正是 fungsi yang dimainkan oleh instruksi noinline, mencegah inline fungsi saat optimasi compiler.

nosplit

Instruksi nosplit berfungsi untuk melewati deteksi overflow stack. Karena model penjadwalan konkurensi go adalah penjadwalan preemptive, asumsikan satu fungsi akan menjalankan kode yang sangat low-level, goroutine lain saat memanggil fungsi ini tidak cocok untuk di-preempt, dapat menggunakan instruksi ini untuk menunjukkan.

go
//go:nosplit
func nospilitFn()

Setelah menggunakan instruksi ini, juga tidak akan ada pertumbuhan stack lagi.

noescape

noescape, dari namanya dapat dengan mudah menebak terkait escape, fungsinya adalah menunjukkan fungsi saat ini tidak akan terjadi perilaku memory escape, setelah eksekusi selesai semua sumber daya akan di-recycle, dan fungsi ini harus hanya memiliki signature tanpa body fungsi, dalam kasus ini umumnya implementasi fungsi diimplementasikan oleh assembly.

Misalnya memhash yang digunakan sebelumnya akan menggunakan instruksi ini

go
//go:noescape
//go:linkname memhash runtime.memhash
func memhash(p unsafe.Pointer, h, s uintptr) uintptr

Dengan begini, compiler tidak akan melakukan analisis escape terhadapnya, prasyaratnya adalah Anda harus memastikan tidak akan terjadi escape, jika terjadi, maka tidak tahu apa konsekuensinya.

uintptrescapes

Instruksi uintptrescapes menunjukkan parameter tipe uinptr dalam fungsi ini dikonversi menjadi nilai pointer dan escape ke heap, dan harus tetap hidup. Instruksi ini umumnya digunakan untuk beberapa sistem call low-level, sebagian besar情况下 tidak perlu memahaminya.

go
//go:uintptrescapes
func nospilit(ptr uintptr) uintptr

Di masa lalu seharusnya ada instruksi notinheaps yang digunakan untuk menunjukkan satu tipe tidak diizinkan mengalokasikan memori ke heap, tidak tahu di versi mana dihapus.

norace

Instruksi norace menunjukkan akses memori satu fungsi tidak lagi memerlukan analisis race condition, umumnya digunakan saat menjalankan kode low-level tidak cocok untuk melakukan analisis race condition.

go
//go:norace
func low_level_code(ptr uintptr) uintptr

TIP

Sebagian instruksi dibatasi hanya dapat digunakan oleh paket runtime, eksternal tidak dapat menggunakannya, mereka akan melibatkan hal yang lebih dalam, ingin memahami dapat melihat pengenalan terkait mereka di Runtime-only compiler directives.

Golang by www.golangdev.cn edit