基础
基础
安装配置
初始化目录
mkdir go
cd go
mkdir src pkg bin
环境变量
# Go 语言安装根目录的路径,也就是 GO 语言的安装路径。
export GOROOT=/usr/local/go
# 若干工作区目录的路径。是我们自己定义的工作空间。
export GOPATH=~/go
# GO 程序生成的可执行文件(executable file)的路径。
export GOBIN=${GOROOT}/bin
export PATH=${PATH}:/usr/local/bin:${GOROOT}/bin:{GOBIN}
Hello Word
初始化项目
go mod init github.com/bihell/dice2/twitter
Hello World 代码
package main
import "fmt"
func main() {
fmt.Println("Hello world")
}
go run cmd/graphqlserver/main.go
编译执行
go build cmd/graphqlserver/main.go
./main
应用程序入口
- 必须是main包:package main,包的名字和目录不需要一定对应
- 必须是main方法:func main()
- 文件明不一定是main.go
编写测试程序
- 源码文件以_test结尾:xxx_test.go
- 测试方法名以Test开头:func TestXXX(t *testing.T)
package try_test
import "testing"
func TestFirstTry(t *testing.T) {
t.Log("My first try!")
}
多变量赋值
func TestExchange(t *testing.T) {
a := 1
b := 2
a,b = b,a
}
快速设定连续常量
const(
Monday = iota + 1
Tuesday
Wednesday
)
位移连续常量
const(
Readable = 1 << itoa
Writable
Executable
)
// 按位与测试
func TestConstantTry1(t *testing.T) {
a := 7 //0111
t.Log(a&Readable==Readable,a&Writable==Writable,a&Executable==Executable)
}
数组
var a [3]int // 声明并初始化为默认零值
a[0] = 1
b := [3]int{1,2,3} //声明同时初始化
arr := [...]int{1,3,4,5} // 不指定长度初始化,根据后面数据的长度。
c := [2][2]int{{1,2},{3,4}} //多维数组初始化
用==比较数组
- 相同维数且含有相同个数元素的数组才可以比较
- 每个元素都相同的才相等
遍历
arr := [...]int{1,3,4,5}
for i :=0; i<len(arr); i++ {
t.Log(arr[i])
}
go 语言独有写法
for idx, e := range arr { t.Log(3) }
数组截取
a[开始索引(包含),结束索引(不包含)]
a := [...]int{1,2,3,4,5}
a[1:2] // 2
a[1:3] // 2,3
a[1:len(a)] //2,3,4,5
a[1:] // 2,3,4,5
a[:3] // 1,2,3
切片
声名非常像数组,但是并没有指定长度
var s0 []int
s1 := []int{1,2,3,4}
s2 := make ([]int,3,5) // 第一个参数是类型,第二个参数是Len,第三个是cap
t.Log(len(s2),cap(s2))
s2 = append(s2,1)
t.Log(len(s2),cap(s2))
每一次cap增长都是前一次乘2
s := []int{}
for i :=0; i < 10; i++ {
s = append(s,i) // 之所以要重新赋值,是因为cap增加之后地址空间发生了变化,并不是在原有地址空间增加这个值,当cap增加时候会创建一个新的连续存储空间,并把原有的值拷贝过去。
t.Log(len(s),cap(s))
}
切片不能比较。
按位置0
const(
Readable = 1 << itoa
Writable
Executable
)
// 按位与测试
func TestConstantTry1(t *testing.T) {
a := 7 //0111
a = a &^ Readable // 按位置0,把可读清掉
t.Log(a&Readable==Readable,a&Writable==Writable,a&Executable==Executable)
}
指针类型
- 不支持指针运算
func TestPoint(t *testing.T) {
a :=1
aPtr := &a
t.Log(a,aPtr)
t.Logf("%T %T",a,aPtr)
aPtr = aPtr +1 // 该操作不支持
)
- string是值类型,默认的初始化值为空字符串,而不是nil
循环
Go 语言仅支持循环关键字for
for j:=7;j<=9;j++
while 条件循环,while (n<5)
n := 0
for n < 5 {
n++
fmt.Println(n)
}
无限循环 while (true)
n := 0
for {
)
if 条件
支持变量赋值
if a := 1 == 1; a{
t.Log("1==1")
}
if v,err := someFun(); err==nil {
t.Log("1==1")
} else {
t.Log("1==1")
}
switch 条件
for i:=0;i<5;i++{
switch i{
case 0,2:
t.Log("Even")
case 1,3:
t.Log("Odd")
default:
t.Log("it is not 0-3")
}
}
for i :=0; i < 5; i++ {
switch {
case i%2==0:
t.Log("Even")
case i%2==1:
t.Log("Odd")
default:
t.Log("unknow")
}
}
源文件代码拆分
hello 函数放在另外一个源码包中
源码一:demo4.go
package main
import (
"flag"
)
var name string
func init() {
flag.StringVar(&name, "name", "everyone", "The greeting object.")
}
func main() {
flag.Parse()
hello(name)
}
源码二:demo4_lib.go
package main
import "fmt"
func hello(name string) {
fmt.Printf("Hello, %s!\n", name)
}
运行
$ go run demo4.go demo4_lib.go
Hello, everyone!
编译
$ go build demo4.go demo4_lib.go
$ ./demo4
Hello, everyone!
# 如果在同一个目录下,可以直接编译目录
$ go build puzzlers/article3/q1
$ ./q1
Hello, everyone!
源码包导入使用
源码一:puzzlers/article3/q2/demo5.go
package main
import (
"flag"
)
var name string
func init() {
flag.StringVar(&name, "name", "everyone", "The greeting object.")
}
func main() {
flag.Parse()
lib.Hello(name)
}
源码二:puzzlers/article3/q2/lib/demo5_lib.go
# 在源码文件中声明所属的代码包与其所在的目录名称要相同
package lib
import "fmt"
# 名称的首字母为大写的程序实体才可以被当前包外的代码引用,否则它就只能被当前包内的其他代码引用。
func Hello(name string) {
fmt.Printf("Hello, %s!\n", name)
}
构建安装代码包
go install puzzlers/article3/q2/lib
其他文档
Map
声明
m := map[string]int{"one":1,"two":2,"three":3}
m1 := map[string]int{}
m1 ["one"]=1
m3 := make(map[int]int,10)
判断key是否存在
if v,ok:=m1[3];ok {
t.Log("存在“)
} else {
t.Log("不存在“)
}
循环
m1 := map[int]int{1:1,2:4,3:9}
for k,v := range m1 {
t.Log(k,v)
}
value 定义成方法
m:=map[int]func(op int)int{}
m[1]:=func(opt int) int {return op}
m[2]:=func(opt int) int {return op*op}
m[3]:=func(op int) int {return op*op*op}
t.Log(m[1](2),m[2](2),m[3](2))
字符串
取出文字对应的UTF编码
s = "中"
c[0] // unicode
c := []rune(s) // utf8
遍历输出
s := "中华人民共和国"
for _, c := range s {
t.Logf("%[1]c %[1]x",c)
}
macOS跨平台编译Linux程序
安装musl-cross
brew install FiloSottile/musl-cross/musl-cross
编译
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC=x86_64-linux-musl-gcc CXX=x86_64-linux-musl-g++ go build -o my-app
或
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC=x86_64-linux-musl-gcc CXX=x86_64-linux-musl-g++ go build -tags musl
linux安装依赖
# Debian
apt-get install -y musl
# Red Hat
wget https://copr.fedorainfracloud.org/coprs/ngompa/musl-libc/repo/epel-7/ngompa-musl-libc-epel-7.repo -O /etc/yum.repos.d/ngompa-musl-libc-epel-7.repo
yum install -y musl-libc-static