本文以 https://tour.golang.org/welcome/1 为主要参考
go和python有点像,是没有分号的。
go中需要 定义package,没有默认包
package main //必须有
import ( // 小括号
"fmt"
"math/rand"
)
// 函数申明时 ,func
func swap(x, y string) (string, string) {// 多返回值
return y, x
}
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return // 直接返回 x y
}
func main() { // 方法名后写返回值,省略则为Void
/* #不是注释 */
//
fmt.Println("My favorite number is", rand.Intn(10)) // 无分号
//包名后方法名 首字母大写 方法名大写,则可以再其他包中调用,小写则不行
// 变量声明
var x int
x = 5
var y = 10
var x,y int = 10,15
x ,y := 1,10
fmt.Println("x type %T", x) //x type int
}
没有初始化的变量会被赋值为零值。 数值型为0,bool 为fasle ,string为“”
go没有默认的类型转换,所有必须强转
float64(1+2)
运行go
# 1
go run hell.go
# 2
go build hell.go# 构建二进制文件
./hell # 运行
常量作为枚举
const (
a = iota //0
b //1
c //2
d = "ha" //独立值,iota += 1
e //"ha" iota += 1
f = 100 //iota +=1
g //100 iota +=1
h = iota //7,恢复计数
i //8
)
fmt.Println(a,b,c,d,e,f,g,h,i)
// 0 1 2 ha ha 100 100 7 8
const 常量由于再声明时就需要初始化,所以可以不写类型
循环 和判断
所有的大括号都不能省略
// for each
for index, value := range slice {}
for i := range slice {}
for _, v := range slice {}
// 标准for
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
// while
sum := 1
for sum < 1000 {
sum += sum
}
// 无限循环
for {
}
// if
if x < 0{
}
defer
可以认为是try catch 中的finally,对整个函数try catch,最后无论是正常执行还是异常退出,都去执行defer
func main() {
fmt.Println("counting")
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
fmt.Println("done")
}
counting
done
9
8
7
6
5
4
3
2
1
0
更多见 https://blog.go-zh.org/defer-panic-and-recover
指针
i, j := 42, 2701
p := &i // 指向 i
fmt.Println(*p) // 通过指针读取 i 的值
*p = 21 // 通过指针设置 i 的值
fmt.Println(i) // 查看 i 的值
结构体 和方法
type Vertex struct {
X int
Y int
}
func change(v Vertex){
v.X =10 // 访问时可以忽略*
(*v).X =10 // c中指针访问
fmt.Println(v.X) // 10
}
func change1(v *Vertex){
v.X =10
fmt.Println(v.X)
}
func main() {
v := Vertex{1, 2}
v.X = 4
fmt.Println(v.X) // 4
change(v)
fmt.Println(v.X) // 4
change1(&v)
fmt.Println(v.X) // 10
}
结构体初始化
可以只初始化部分参数,类似python函数中部分有默认值的参数可以省略。toString也不需要搞,自动带一个
var (
v1 = Vertex{1, 2} // 创建一个 Vertex 类型的结构体
v2 = Vertex{X: 1} // Y:0 被隐式地赋予
v3 = Vertex{} // X:0 Y:0
p = &Vertex{1, 2} // 创建一个 *Vertex 类型的结构体(指针)
)
func main() {
fmt.Println(v1, p, v2, v3)
// {1 2} &{1 2} {1 0} {0 0}
}
go没有类,但可以给结构体写方法
// 方法,输入即可以是 值也可以是指针,区别同传值和传指针
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
// 必须传入指针,即&p
func ScaleFunc(v *Vertex, f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
go中nil对象也能调用方法,古再方法中需要自行判断
JAVA中父的toString方法,go中使用String
// 结构体转string
func (p Person) String() string {
return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}
数组和切片
数组传递时是传值,即copy,和JAVA中有明显区别。如果要传递数组的话,可以考虑传指针或传切片。
数组。go中数组和其长度是绑定的,如果函数要返回一个数组,那么再返回值中必须指明数组的大小。
//数组创建
var a [10]int
return int[10]int{}
// 返回数组
func get() [10]int{
return [10]int{}
}
//数组和切片还是有区别的
func Pic(dx, dy int) [][]int{
var img [10][10] int
return img
}
// cannot use img (type [10][10]int) as type [][]int in return argument
go中对数组的使用过于死板,故常使用切片。
切片相当于数组的一个指针。和python中的数组类似
切片和底层的数组也是绑定的,切片的所有操作都是在底层数组上,而不是切片上。
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s) // len=6 cap=6 [2 3 5 7 11 13]
// 截取切片使其长度为 0
s = s[:0]
printSlice(s)// len=0 cap=6 []
// 拓展其长度
s = s[:4]
printSlice(s)// len=4 cap=6 [2 3 5 7]
// 舍弃前两个值
s = s[2:]
printSlice(s)// len=2 cap=4 [5 7]
var s []int
printSlice(s)
// 添加一个空切片
s = append(s, 0)
printSlice(s)
// 这个切片会按需增长
s = append(s, 1)
printSlice(s)
// 可以一次性添加多个元素
s = append(s, 2, 3, 4)
printSlice(s)
// 将一
s = append(s,b...)
二维切片的操作
func Pic(dx, dy int) [][]uint8 {
img := make([][]uint8,dy)
for i := range img{
img[i] = make([]uint8,dx)
for j := range img[i]{
img[i][j] = uint8(i*j)
}
}
return img
}
映射
实现 WordCount。它应当返回一个映射,其中包含字符串 s 中每个“单词”的个数。函数 wc.Test 会对此函数执行一系列测试用例,并输出成功还是失败。
package main
import (
"golang.org/x/tour/wc"
"strings"
)
func WordCount(s string) map[string]int {
m := make(map[string]int)
for _, w := range strings.Fields(s) {
m[w] = m[w]+1
}
return m
}
func main() {
wc.Test(WordCount)
}
https://blog.go-zh.org/go-slices-usage-and-internals
函数
package main
import "fmt"
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
func main() {
pos, neg := adder(), adder()// 两个“对象"
for i := 0; i < 10; i++ {
fmt.Println(
pos(i),
neg(-2*i),
)
}
}
0 0
1 -2
3 -6
6 -12
10 -20
15 -30
21 -42
28 -56
36 -72
45 -90
并行
奇奇怪怪的语法
- 大括号
{ 不能单独一行
- 变量未使用
如果有变量未使用,则编译失败
package main
import (
"fmt"
)
func main(){
var x int = 10
fmt.Println("hello")
// _ = x 添加该行后可解决该问题
}
// ** x declared but not used**
go中对该问题的解释时,有未使用的变量可能会有bug。 Can I stop these complaints about my unused variable/import?
但全局变量是可以声明后不使用的。
reference
https://tour.golang.org/welcome/1
https://www.runoob.com/go/go-tutorial.html

被折叠的 条评论
为什么被折叠?



