Go Cheatsheet
January 21, 2025 · 13 min read · Page View:
If you have any questions, feel free to comment below.
syntax #
- The uppercase of the first letter of const, var, func, type is exported. And the lowercase is private.
- The
{
cannot be as a separate line. - Not need to use
;
to end the statement.(Not recommend) //
or/* */
can be used to comment.- the string can be connected by
+
fmt.Printf
is used to print the string format.
dependency #
go get #
go env
# GOROOT='/usr/local/go' // the standard library
# GOPATH='/Users/username/go' // the project lib or three-party lib
go get will download the three-party lib to the GOPATH/src
directory. The go search GOROOT first, then search GOPATH. But the denpendency only can keep one version, which will cause some conflict.
go vendor #
Save all the denpendency in the vendor
directory of the project, which make the project more redundant. The go will search the vendor first. This still cannot solve the problem of version.
go module #
It was introduced in go1.11, which can manage the denpendency more flexibly.
go mod init
first initialize the project denpendency.go mod tidy
write the using denpendency to thego.mod
file and remove the unused denpendency in the file.go mod download
orgo build
orgo test
, the three-party lib will be downloaded to theGOPATH/pkg/mod
directory.
indirect
means the sub-denpendency.
+incompatible
means compatible with the old version without the go.mod file.
If the project different package needs the same denpendency’s different version, it will choose the minimum compatible version.
denpendency distribution #
Normally use the GOPROXY='https://proxy.golang.org,direct'
search the proxy first, if not found, then search the original source.
data type #
Int float..
: default is0
String
: default is""
Bool
: default isfalse
Below are all nil.
var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error
var #
// case1
var identifier1, identifier2 type
// usually used in global variable
var (
vname1 v_type1
vname2 v_type2
)
// case2 only can be used in function
intVal := 1 // you cannot declare the variable twice
// which is equivalent to var intVal int = 1
var intVal int
intVal =1
// case3 auto
var v1name, v2name = value1, value2
The int, float, bool and string are basic value type, using these types of variables directly save the value in memory, if use such as i = j
, then actually copy the value of j
to i
in memory. &i
is used to get the address of i
in memory. When the i is local variable, the address is in the stack, when the i is global variable, the address is in the heap.
The complex type is a pointer, slice, map, channel, function, interface, struct, they are usually used as reference type. The reference type usually save the address of the value in memory, if use such as i = j
, then actually copy the address of j
to i
in memory. So if j changes reference value, i will also change.
You cannot declare a var but not use it in function. Except the global variable.
You can use a, b = b, a
to swap the value of a and b.(Must be the same type)
Use _
to drop value, such as _, b = a, b
const #
// type only boolen, string, number
const identifier [type] = value
You can use the build-in function to operate the const.
import "unsafe"
const (
a = "abc"
b = len(a)
c = unsafe.Sizeof(a)
)
iota #
special const, default is 0, every time add one const, the iota will add one.
And in the const block, if you don’t assign the value obviously, it will inherit the last value.
func main() {
const (
a = iota //0
b //1
c //2
d = "ha" //"ha" iota += 1
e //"ha" iota += 1
f = 100 //100 iota +=1
g //100 iota +=1
h = iota //7
i //8
)
}
operator #
&: get the address of the variable.
- pointer variable: get the value of the address.
package main
import "fmt"
func main() {
var a int = 4
var b int32
var c float32
var ptr *int
ptr = &a
fmt.Printf("a is %d\n", a); // a is 4
fmt.Printf("*ptr is %d\n", *ptr); // *ptr is 4
}
if #
if num := 9; num < 0 {
fmt.Println(num, "is negative")
} else if num < 10 {
fmt.Println(num, "has 1 digit")
} else {
fmt.Println(num, "has multiple digits")
}
switch #
switch var1 {
case val1:
// do something
case val2:
// do something
default:
// do something
}
switch x.(type){
case type:
statement(s);
case type:
statement(s);
default: // optional
statement(s);
}
// the fallthrough will execute the next case forcefully.
func main() {
switch {
case false:
fmt.Println("1")
fallthrough
case true:
fmt.Println("2")
fallthrough
case false:
fmt.Println("3")
fallthrough
case true:
fmt.Println("4")
case false:
fmt.Println("5")
fallthrough
default:
fmt.Println("6")
}
}
// 2 3 4
select #
select only can be used in channel, each case must be a channel operation, either send or receive.
select {
case <-ch1:
// do something
case value := <- channel2:
// do something
case channel3 <- value:
// do something
default:
// do something
}
select statement will listen to all the channel operations, once one channel is ready, then execute the corresponding code block. If multiple channels are ready, then the select statement will randomly select one channel to execute. If all channels are not ready, then execute the code in the default block. if there is no default, select will block until one channel is ready. Go will not re-evaluate the channel or value.
for #
for n := 0; n < 5; n++ {
if n%2 == 0 {
continue
}
fmt.Println(n)
}
// infinite loop
for {
fmt.Println("loop")
break
}
array #
It is fixed length, which is not common used.
var twoD [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
twoD[i][j] = i + j
}
}
slice #
func main() {
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("get:", s[2]) // c
fmt.Println("len:", len(s)) // 3
s = append(s, "d") // must be received back
s = append(s, "e", "f")
fmt.Println(s) // [a b c d e f]
c := make([]string, len(s))
copy(c, s)
fmt.Println(c) // [a b c d e f]
fmt.Println(s[2:5]) // [c d e]
fmt.Println(s[:5]) // [a b c d e]
fmt.Println(s[2:]) // [c d e f]
good := []string{"g", "o", "o", "d"}
fmt.Println(good) // [g o o d]
}
map #
func main() {
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m) // map[one:1 two:2]
fmt.Println(len(m)) // 2
fmt.Println(m["one"]) // 1
fmt.Println(m["unknow"]) // 0
r, ok := m["unknow"]
fmt.Println(r, ok) // 0 false
delete(m, "one")
m2 := map[string]int{"one": 1, "two": 2}
var m3 = map[string]int{"one": 1, "two": 2}
fmt.Println(m2, m3)
}
range #
func main() {
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num) // index: 0 num: 2
}
}
fmt.Println(sum) // 9
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
fmt.Println(k, v) // b 8; a A
}
for k := range m {
fmt.Println("key", k) // key a; key b
}
}
func #
- not support nested
- not support overload
- not support default parameter
- return can only be received by multiple values
x, _
cannot use a container to receive
// func name(parameter-list) (return-list)
func add(a int, b int) int {
return a + b
}
func add2(a, b int) int {
return a + b
}
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
func main() {
res := add(1, 2)
fmt.Println(res) // 3
v, ok := exists(map[string]string{"a": "A"}, "a")
fmt.Println(v, ok) // A True
}
func myfunc(args ...interface{}) { // pass any type of parameter
}
func add(a int, b int, args…int) int { //2 parameters or more
// the args is a slice you can use it via args[index]
}
//eg.
func test(s string, n ...int) string {
var x int
for _, i := range n {
x += i
}
return fmt.Sprintf(s, x)
}
func main() {
s := []int{1, 2, 3}
res := test("sum: %d", s...) // slice... (expand slice)
println(res)
}
lambda function #
In go, the lambda function is a closure.
getSqrt := func(a float64) float64 {
return math.Sqrt(a)
}
fmt.Println(getSqrt(4))
The function is a first-class citizen in the language. Generally, a function returns another function, which can reference the local variables of the outer function, forming a closure.
Usually, a closure is implemented through a structure, which stores a function and an associated context environment. But in Go, the anonymous function is a closure, which can directly reference the local variables of the outer function.
closure #
package main
import "fmt"
func add(base int) func(int) int {
return func(i int) int {
base += i
return base
}
}
func main() {
tmp1 := add(10) // base is 10;
// tmp1 is returned func(i)
// in fact the tmp1 is a `FuncVal` object, FuncVal { func_address, closure_var_pointer ... } which contains:
// 1. the anonymous function address
// 2. the closure object pointer, which points to the closure object that contains the required external variables.
// the function call usually involves passing parameters to the function and jumping to the function's entry address for execution.
// **then FuncVal object is obtained, and the anonymous function address and the closure object pointer are obtained**, completing the function call and correctly accessing the required external variables.
// the closure is indirectly expanded the life cycle of function.
fmt.Println(tmp1(1), tmp1(2)) // 11 13
// this tmp2 is a new entity
tmp2 := add(100)
fmt.Println(tmp2(1), tmp2(2)) // 101 103
}
defer #
- The keyword defer is used to register a deferred call.
- These calls are executed just before the return. Therefore, it can be used for resource cleanup.
- Multiple defer statements are executed in a FILO manner. Even if is a panic.
- The variables in the defer statement are determined when the defer statement is declared.
Often used in:
- Close file handle
- Release lock resource
- Release database connection
// defer in closure
package main
import "fmt"
func main() {
var whatever [5]struct{}
for i := range whatever {
defer func() { fmt.Println(i) }()
}
}
Each time a “defer” statement executes, the function value and parameters to the call are evaluated as usualand saved anew but the actual function is not invoked.
package main
func test() {
x, y := 10, 20
defer func(i int) {
println("defer:", i, y) // y is a closure reference, will be executed until the test function return
}(x) // (x) means calling the function right now, x is copied to i, but the function is deferred, so it will be executed after the test function return
x += 10
y += 100
println("x =", x, "y =", y)
}
func main() {
test()
}
// x = 20 y = 120
// defer: 10 120
pointer #
func add2(n int) {
n += 2
}
func add2ptr(n *int) {
*n += 2
}
func main() {
n := 5
add2(n)
fmt.Println(n) // 5
add2ptr(&n)
fmt.Println(n) // 7
}
struct #
type user struct {
name string
password string
}
func main() {
// 1
a := user{name: "wang", password: "1024"}
// 2
b := user{"wang", "1024"}
// 3
c := user{name: "wang"}
c.password = "1024"
// 4
var d user
d.name = "wang"
d.password = "1024"
fmt.Println(a, b, c, d) // {wang 1024} {wang 1024} {wang 1024} {wang 1024}
fmt.Println(checkPassword(a, "haha")) // false
fmt.Println(checkPassword2(&a, "haha")) // false
}
func checkPassword(u user, password string) bool {
return u.password == password
}
// if use pointer, you can make some changes and avoid some big structure cost
func checkPassword2(u *user, password string) bool {
return u.password == password
}
// the structure method
func (u user) checkPassword(password string) bool {
return u.password == password
}
// You can change the value via pointer
func (u *user) resetPassword(password string) {
u.password = password
}
func main() {
a := user{name: "wang", password: "1024"}
a.resetPassword("2048")
fmt.Println(a.checkPassword("2048")) // true
}
exception #
panic throw the error, recover catch the error.
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
var ch chan int = make(chan int, 10)
close(ch)
ch <- 1
}
// send on closed channel
error #
Besides, panic causes a fatal system error, and can also return an error object to represent the status of the function call.
import (
"errors"
"fmt"
)
type user struct {
name string
password string
}
func findUser(users []user, name string) (v *user, err error) {
for _, u := range users {
if u.name == name {
return &u, nil
}
}
return nil, errors.New("not found")
}
func main() {
if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err) // not found
return
} else {
fmt.Println(u.name)
}
}
string #
import (
"fmt"
"strings"
)
func main() {
a := "hello"
fmt.Println(strings.Contains(a, "ll")) // true
fmt.Println(strings.Count(a, "l")) // 2
fmt.Println(strings.HasPrefix(a, "he")) // true
fmt.Println(strings.HasSuffix(a, "llo")) // true
fmt.Println(strings.Index(a, "ll")) // 2
fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // he-llo
fmt.Println(strings.Repeat(a, 2)) // hellohello
fmt.Println(strings.Replace(a, "e", "E", -1)) // hEllo
fmt.Println(strings.Split("a-b-c", "-")) // [a b c]
fmt.Println(strings.ToLower(a)) // hello
fmt.Println(strings.ToUpper(a)) // HELLO
fmt.Println(len(a)) // 5
b := "你好"
fmt.Println(len(b)) // 6
}
fmt #
type point struct {
x, y int
}
func main() {
s := "hello"
n := 123
p := point{1, 2}
// %v: value
fmt.Printf("s=%v\n", s) // s=hello
fmt.Printf("n=%v\n", n) // n=123
fmt.Printf("p=%v\n", p) // p={1 2}
// %+v: value with field name
fmt.Printf("p=%+v\n", p) // p={x:1 y:2}
// more detail
fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}
f := 3.141592653
fmt.Println(f) // 3.141592653
fmt.Printf("%.2f\n", f) // 3.14
}
json #
import (
"encoding/json"
"fmt"
)
type userInfo struct {
// you should make sure the uppercase of field name
Name string
Age int `json:"age"`
Hobby []string
}
func main() {
a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
// Marshal: convert struct to json
buf, err := json.Marshal(a)
if err != nil {
panic(err)
}
// hex code
fmt.Println(buf) // [123 34 78 97...]
// convert to string
fmt.Println(string(buf)) // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}
buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(buf))
var b userInfo
err = json.Unmarshal(buf, &b)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", b) // main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}}
}
time #
import (
"fmt"
"time"
)
func main() {
now := time.Now()
fmt.Println(now) // 2022-03-27 18:04:59.433297 +0800 CST m=+0.000087933
t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)
t2 := time.Date(2022, 3, 27, 2, 30, 36, 0, time.UTC)
fmt.Println(t) // 2022-03-27 01:25:36 +0000 UTC
fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute()) // 2022 March 27 1 25
fmt.Println(t.Format("2006-01-02 15:04:05")) // 2022-03-27 01:25:36
diff := t2.Sub(t)
fmt.Println(diff) // 1h5m0s
fmt.Println(diff.Minutes(), diff.Seconds()) // 65 3900
t3, err := time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:36")
if err != nil {
panic(err)
}
fmt.Println(t3 == t) // true
fmt.Println(now.Unix()) // 1648738080
}
strconv #
import (
"fmt"
"strconv"
)
func main() {
f, _ := strconv.ParseFloat("1.234", 64)
fmt.Println(f) // 1.234
// str base precision
n, _ := strconv.ParseInt("111", 10, 64)
fmt.Println(n) // 111
n, _ = strconv.ParseInt("0x1000", 0, 64)
fmt.Println(n) // 4096
// convert quickly
n2, _ := strconv.Atoi("123")
fmt.Println(n2) // 123
n2, err := strconv.Atoi("AAA") // invalid
fmt.Println(n2, err) // 0 strconv.Atoi: parsing "AAA": invalid syntax
}
os #
import (
"fmt"
"os"
"os/exec"
)
func main() {
// go run example/20-env/main.go a b c d
fmt.Println(os.Args) // [/var/folders/8p/n34xxfnx38dg8bv_x8l62t_m0000gn/T/go-build3406981276/b001/exe/main a b c d]
fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...
fmt.Println(os.Setenv("AA", "BB"))
buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()
if err != nil {
panic(err)
}
fmt.Println(string(buf)) // 127.0.0.1 localhost
}
If you find this blog useful and want to support my blog, need my skill for something, or have a coffee chat with me, feel free to: