虚拟包版本
Untagged revisions can be referred to using a “pseudo-version” like v0.0.0-yyyymmddhhmmss-abcdefabcdef, where the time is the commit time in UTC and the final suffix is the prefix of the commit has
go get github.com/vladimirvivien/go4vl@40b41ba
go get: upgraded github.com/vladimirvivien/go4vl v0.0.1 => v0.0.2-0.20211216162907-40b41ba86c5c
类型转换操作
For every type T, there is a corresponding conversion operation T(x) that converts the value x to >type T. A conversion from one type to another is allowed if both have the same underlying type, or >if both are unnamed pointer types that point to variables of the same underlying type; these >conversions change the type but not the representation of the value. If x is assignable to T, a >conversion is permitted but is usually redundant.
blank identifier
To ignore one of the values, assign it to the blank identifier :
links, _ := findLinks(url) // errors ignored
for _, url := range os.Args[1:] {
import
ImportDeclaration = "import" ImportSpec
ImportSpec = [ "." | "_" | Identifier ] ImportPath
According to language spec it depends on the implementation how
import path (string) is interpreted but in real life it’s path
relative package’s vendor directory or go env GOPATH
/src
定制的包名
# github.com/mlowicki/main.go package main import ( "fmt" "github.com/mlowicki/b" ) func main() { fmt.Println(c.B) } # github.com/mlowicki/b/b.go package c var B = "b"
初始化
import _ "math"
doesn’t require to use package math in importing file but init function(s) from imported package will be executed anyway (package and it dependencies will be initialized). It’s useful if we’re interested only in bootstrapping work done by imported package but we don’t reference any exported identifiers from it.
How to check if a map contains a key
func TestMap(t *testing.T){
attended := map[string]string{
"Ann": "t",
"Joe": "r",
}
val, ok := attended["mm"]
fmt.Print(val, ok)
}
if statements in Go can include both a condition and an initialization statement. The example above uses both:
initializes two variables - val will receive either the value of “foo” from the map or a “zero value” (in this case the empty string) and ok will receive a bool that will be set to true if “foo” was actually present in the map
evaluates ok, which will be true if “foo” was in the map
Constructors
two accepted best practices:
- Make the zero value of your struct a sensible default. (While this looks strange to most people coming from “traditional” oop it often works and is really convenient).
- Provide a function func New() YourTyp or if you have several such types in your package functions func NewYourType1() YourType1 and so on.
Document if a zero value of your type is usable or not (in which case it has to be set up by one of the New… functions
empty interface (interface{} is an empty interface)
An interface is two things:
it is a set of methods,
but it is also a type
The interface{} type, the empty interface is the interface that has no methods.
Since there is no implements keyword, all types implement at least zero methods, and satisfying an interface is done automatically,all types satisfy the empty interface.
That means that if you write a function that takes an interface{} value as a parameter, you can supply that function with any value.
Method’s receiver
go don’t user special name like( this or self ) for the receiver
func (p Point) MoveBy(factor float){ p.X += factor //-> this.X += factor }
Pointer receiver
project-layout Internal app/pkg Directory Clarification
Using /internal/pkg is about consistency if you use the /pkg pattern. The public shared code goes in ‘/pkg’ and the private shared code goes in /internal/pkg
https://github.com/golang-standards/project-layout/issues/9
vendor package
go help gopath
find . -name grpc | xargs rm -rf
/go/pkg/mod/google.golang.org$ ls
[email protected] [email protected] [email protected] [email protected]
Vendor directories do not affect the placement of new repositories being checked out for the first time by ‘go get’: those are always placed in the main GOPATH, never in a vendor subtree
remove installed package
go clean -i -n google.golang.org/grpc...
cd /home/bigo/go/src/google.golang.org/grpc
rm -f grpc.test grpc.test.exe
rm -f /home/bigo/go/pkg/linux_amd64/google.golang.org/grpc.a
cd /home/bigo/go/src/google.golang.org/grpc/balancer
rm -f balancer.test balancer.test.exe
rm -f /home/bigo/go/pkg/linux_amd64/google.golang.org/grpc/balancer.a
cd /home/bigo/go/src/google.golang.org/grpc/balancer/base
rm -f base.test base.test.exe
rm -f /home/bigo/go/pkg/linux_amd64/google.golang.org/grpc/balancer/base.a
cd /home/bigo/go/src/google.golang.org/grpc/balancer/grpclb
rm -f grpclb.test grpclb.test.exe
identifier export
In Go, a simple rule governs which identifiers are exported and which are not: exported identifiers start with an upper-case letter
Package-level names like the types and constants declared in one file of a package are visible to all the other files of the package, as if the source code were all in a single file
CSP
“Another lineage among Go’s ancestors, and one that makes Go distinctive among recent programming languages, is a sequence of little-known research languages developed at Bell Labs, all inspired by the concept of communicating sequential processes (CSP) from Tony Hoare’s seminal 1978 paper on the foundations of concurrency. In CSP, a program is a parallel composition of processes that have no shared state; the processes communicate and synchronize using channels.”
hindsight
“As a recent high-level language, Go has the benefit of hindsight, and the basics are done well: it has garbage collection, a package system, first-class functions, lexical scope, a system call interface, and immutable strings in which text is generally encoded in UTF-8. But it has comparatively few features and is unlikely to add more. For instance, it has no implicit numeric conversions, no constructors or destructors, no operator overloading, no default parameter values, no inheritance, no generics, no exceptions, no macros, no function annotations, and no thread-local storage”
gofmt
Go does not require semicolons at the ends of statements or declarations, except where two or more appear on the same line. In effect, newlines following certain tokens are converted into semicolons, so where newlines are placed matters to proper parsing of Go code. For instance, the opening brace { of the function must be on the same line as the end of the func declaration, not on a line by itself, and in the expression x + y, a newline is permitted after but not before the + operator.
point var
- “The variable to which p points is written *p. The expression *p yields the value of that variable, an int, but since *p denotes a variable, it may also appear on the left-hand side of an assignment, in which case the assignment updates the variable.”
- “Expressions that denote variables are the only expressions to which the address-of operator & may be applied.”
- “Each time we take the address of a variable or copy a pointer, we create new aliases or ways to identify the same variable. For example, *p is an alias for v.”
Function Values have types
declare a var with function value as type * func(int) int -> type
var f func(int) int
nil pointer dereference
package main
import "fmt"
var f func(int) int
func main() {
//fmt.Println(f(2))
fmt.Println(f(2))
f = func(i int) int {
if i == 0 {
return 1
}
return i * f(i-1)
}
fmt.Println(f(2))
}
panic: runtime error: invalid memory address or nil pointer dereference[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4850f0]goroutine 1 [running]:main.main() /home/bigo/go/src/github.com/gopl.io/ch5/t2/main.go:9 +0x30exit status 2Process exiting with code: 1
Capturing Iteration Variables
“The problem of iteration variable capture is most often encountered when using the go statement or with defer since both may delay the execution of a function value until after the loop has finished. But the problem is not inherent to go or defer.”
var s1 [3]int = [3]int{1, 2, 3}
var fs []func()
func main() {
for _, v := range s1 {
//fmt.Printf("%d\n", v)
fs = append(fs, func() {
fmt.Printf("%d\n", v) //v is caputed and shared
})
}
for _, f := range fs {
f()
}
fs = nil
for _, v := range s1 {
i := v
fs = append(fs, func() {
fmt.Printf("%d\n", i)
})
}
for _, f := range fs {
f()
}
}
The reason is a consequence of the scope rules for loop variables. In the program immediately above, the for loop introduces a new lexical block in which the variable dir is declared. All function values created by this loop “capture” and share the same variable—an addressable storage location, not its value at that particular moment. The value of dir is updated in successive iterations, so by the time the cleanup functions are called, the dir variable has been updated several times by the now-completed for loop.
expression in go/defer must be function call
express anonymous function as function call()
var s1 [3]string = [3]string{"go", "func", "value"} func f(s string) { fmt.Println(s) } func main() { fmt.Println("s escapsed") for _, s := range s1 { defer func() { fmt.Println(s) }() } fmt.Println("work expected") for _, s := range s1 { defer func(s string) { fmt.Println(s) }(s) } for _, s := range s1 { defer f(s) } for _, s := range s1 { go func(s string) { fmt.Println("h %s", s) }(s) } for _, s := range s1 { go f(s) } }
install go-1.10
***vscode will report go-runtime read-only error which has been installed via snap
sudo add-apt-repository ppa:gophers/archive
sudo apt-get update
sudo apt-get install golang-1.10-go
export GOROOT="/usr/lib/go-1.10"
export GOPATH=$HOME/go
export PATH="$PATH:$GOPATH/bin:$GOROOT/bin/"
go version
GOPATH directory
cd $GOPATH
ls
src bin pkg
DIR | |
---|---|
pkg | 存放编译过的包 |
bin | 存放可执行程序(package main) |
import path两个功能
go help importpath
在本地文件系统$GOPATH/pkg/$GOOS_$GOARCH/
查找 import "github.com/google/go-github/github" ... go/src/wubigo.com/cloud/github_client/main.go:7:2: cannot find package "github.com/google/go-github/github" in any of: /usr/lib/go-1.11/src/github.com/google/go-github/github (from $GOROOT) /home/bigo/go/src/github.com/google/go-github/github (from $GOPATH) Process exiting with code: 1 ...
如果没找到,需要go get通过
安装 go get github.com/google/go-github/github
import path custom domain name
curl golang.org/x/tools/cmd/rename <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta name="go-import" content="golang.org/x/tools git https://go.googlesource.com/tools"> <meta name="go-source" content="golang.org/x/tools https://github.com/golang/tools/ https://github.com/golang/tools/tree/master{/dir} https://github.com/golang/tools/blob/master{/dir}/{file}#L{line}"> <meta http-equiv="refresh" content="0; url=https://godoc.org/golang.org/x/tools/cmd/rename"> </head> <body> Nothing to see here; <a href="https://godoc.org/golang.org/x/tools/cmd/rename">move along</a>. </body>
Canonical import paths
The syntax is simple: put an identifying comment on the package line
https://github.com/golang/tools/blob/master/cmd/gorename/main.go
package main // import "golang.org/x/tools/cmd/gorename"
struct tags
- List of well-known struct tags
field tags
A field tag is a string of metadata associated at compile time with the field of a struct:
Year int `json:"released"`
Color bool `json:"color,omitempty"`
A field tag may be any literal string , but it is conventionally interpreted as a space-separated list of key:“value” pairs; since they contain double quotation marks, field tags are usually written with raw string literals. The json key control s the behavior of the encoding/json package, and other encoding/… packages follow this convention. The first part of the json field tag specifies an alternative JSON name for the Go field