package main import"fmt" funcmain() { fmt.Println("Hello World") }
0x03 GO 语言基础
1. 类型
字符串类型
1 2 3 4 5 6 7 8 9 10 11
package main import"fmt" funcsayHello(s string)string { return"Hello " + s } funcmain() { fmt.Println(sayHello("Drunkbaby")) }
int 类型
1 2 3 4 5 6 7 8 9 10 11
package main import"fmt" funcaddition(x int, y int)int { return x+y } funcmain() { fmt.Println(addition(2,4)) }
bool 类型
1 2 3 4 5 6 7 8 9 10
package main import"fmt" funcmain() { var b bool fmt.Println(b) b = true fmt.Println(b) }
数值类型
int:平平无奇
float:氛围 float32 与 float64,一般用 float64 居多
定义如下
1
var f float64 = 0.111
类型转换
此处提及两个包,一个是 reflect,一个是 srtconv
1 2 3 4 5 6 7 8 9 10 11 12
package main import ( "fmt" "reflect""strconv") funcmain() { var b bool = true fmt.Println(reflect.TypeOf(b)) var s string = strconv.FormatBool(true) fmt.Println(reflect.TypeOf(s)) }
2. 变量
字符串变量
1 2 3 4 5 6 7 8
package main import"fmt" funcmain() { var s string = "Hello World" fmt.Println(s) }
快捷声明变量
1 2 3 4 5 6 7 8 9 10 11 12
package main import"fmt" funcmain() { var ( s string = "Drunkbaby" i int = 4 ) fmt.Println(s) fmt.Println(i) }
声明变量后,就不能再次声明它,不然会报错。
变量零值
1 2 3 4 5 6 7 8 9 10 11
package main import"fmt" funcmain() { var i int var f float64 var b bool var s string fmt.Printf("%v %v %v %q\n", i, f, b, s) }
编写简短变量
:= 符号是简短变量声明
1 2 3 4 5 6 7 8
package main import"fmt" funcmain() { s := "Hello World" fmt.Println(s) }
简短变量声明是最常用的变量声明方式,还有一些比较简洁的变量声明
1 2 3 4 5 6 7 8 9 10 11
package main import"fmt" var s = "Hello World" funcmain() { i := 42 fmt.Println(s) fmt.Println(i) }
有关作用域
和其他语言是一样的,大括号作为作用域的分割,看代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
package main import"fmt" var s2 = "Hello World" funcmain() { fmt.Printf("Print 's2' variable from outer block %v\n", s2) b := true if b { fmt.Printf("Printing 'b' variable from outer block %v\n", b) i := 42 if b != false { fmt.Printf("Printing 'i' variable from outer block %v\n", i) } } }
指针
1 2 3 4 5 6 7 8
package main import"fmt" funcmain() { s := "Hello World" fmt.Println(&s) }
输出一个十六进制的内存地址
将变量作为值传递时,地址不变
1 2 3 4 5 6 7 8 9 10 11 12 13 14
package main import"fmt" funcshowMemoryAddress(x *int) { fmt.Println(x) return } funcmain() { i := 1 fmt.Println(&i) showMemoryAddress(&i) }
package main import"fmt" funcgetPrize() (int, string) { i := 2 s := "Drunkbaby" return i, s } funcmain() { quantity, prize := getPrize() fmt.Printf("You won %v %v\n", quantity, prize) }
不定参数函数
很有意思,是用三个点的,变量 numbers 是一个包含所有参数的切片。
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
package main import"fmt" funcsumNumbers(numbers... int)int { total := 0 for _, number := range numbers { total += number } return total } funcmain() { result := sumNumbers(1, 2, 3, 4) fmt.Printf("The result is %v\n", result) }
具名返回值
按照声明顺序返回具体名称变量值。
1 2 3 4 5 6 7 8 9 10 11 12 13
package main import"fmt" funcsayHi() (x, y string) { x = "hello" y = "world" return } funcmain() { fmt.Println(sayHi()) }
package main import"fmt" funcmain() { b := true if b { fmt.Println("b is true!") } }
else
1 2 3 4 5 6 7 8 9 10 11 12
package main import"fmt" funcmain() { b := false if b { fmt.Println("b is true") } else { fmt.Println("b is false") } }
elseif
1 2 3 4 5 6 7 8 9 10 11 12
package main import"fmt" funcmain() { i := 3 if i == 3 { fmt.Println("i is 3") } elseif i == 2 { fmt.Println("i is 2") } }
运算符
算术运算符
逻辑运算符
switch,可以说是 if 的高级用法了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
package main import"fmt" funcmain() { i := 2 switch i { case2: fmt.Println("Two") case3: fmt.Println("Three") case4: fmt.Println("Four") } }
default in switch 语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
package main import"fmt" funcmain() { s := "c" switch s { case"a": fmt.Println("The letter is a!") case"b": fmt.Println("The letter is b!") default: fmt.Println("I don't recognize that letter") } }
for 循环
1 2 3 4 5 6 7 8 9 10 11
package main import"fmt" funcmain() { i := 0 for i < 10 { i++ fmt.Println("i is", i) } }
简化写法,也是最常规的写法
1 2 3 4 5 6 7 8 9
package main import"fmt" funcmain() { for i := 0; i < 10; i++ { fmt.Println("i is", i) } }
包含 range 子句的 for 语句
1 2 3 4 5 6 7 8 9 10 11
package main import"fmt" funcmain() { numbers := []int{1,2,3,4} for i, n := range numbers { fmt.Println("The index of the loop is", i) fmt.Println("The value from the array is", n) } }
defer 语句
defer 是一个很有用的 Go 语言功能,它能够让程序在函数返回前执行另一个函数。函数在遇到 return 语句或到达函数末尾的时候返回。defer 语句通常用于执行清理操作或确保操作。
1 2 3 4 5 6 7 8
package main import"fmt" funcmain() { defer fmt.Println("I am run after the function completes") fmt.Println("Hello World") }
在执行完 main 函数后执行 defer 函数
5. 数组、切片和映射
数组的相关基础操作
1 2 3 4 5 6 7 8 9 10 11 12
package main import"fmt" funcmain() { var cheeses [2]string cheeses[0] = "Silly" cheeses[1] = "Drunkbaby" fmt.Println(cheeses[0]) fmt.Println(cheeses[1]) fmt.Println(cheeses) }
package main import"fmt" type Movie struct { Name string Rating float32 } funcmain() { m := Movie{ Name: "Drunkbaby", Rating: 10, } fmt.Println(m.Name, m.Rating) }
“实例化一个 struct 实例”
和 new 一个 class 一样,比较简单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
package main import"fmt" type Person struct { Name string Rating float32 } funcmain() { var m Person fmt.Printf("%+v\n", m) m.Name = "Drunkbaby" m.Rating = 10 fmt.Printf("%+v\n", m) }
“new 一个 struct 实例”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
package main import"fmt" type Student struct { Name string Age float32 } funcmain() { m := new(Student) m.Name = "Drunkbaby" m.Age = 10 fmt.Printf("%+v\n", m) }
package main import"fmt" type Superhero struct { Name string Age int Address Address } type Address struct { Number int Street string City string } funcmain() { e := Superhero{ Name: "Batman", Age: 32, Address: Address{ Number: 1007, Street: "Mountain Drive", City: "Gotham", }, } fmt.Printf("%+v\n", e) }
package main import"fmt" type Drink struct { Name string Ice bool } funcmain() { a := Drink{ Name: "Lemonade", Ice: true, } b := Drink{ Name: "Lemonade", Ice: true, } if a == b { fmt.Println("a and b are the same") } fmt.Printf("%+v\n", a) fmt.Printf("%+v\n", b) }
检查结构体类型
在 go 里面用的是 reflect,挺有意思的,在 Java 里面这也被称作反射,不愧是反射,能够看到结构体是什么
package main import"fmt" type work struct { Name string isWork bool } funcmain() { a := work{ Name: "Fire", isWork: true, } b := a b.isWork = false fmt.Printf("%+v\n", b) fmt.Printf("%+v\n", a) fmt.Printf("%p\n", &a) fmt.Printf("%p\n", &b) }
package main import ( "errors" "fmt") type Robot interface { PowerOn() error } type T850 struct { Name string } func(a *T850) PowerOn() error { returnnil } type R2D2 struct { Broken bool } func(r R2D2) PowerOn() error { if r.Broken { return errors.New("R2D2 is broken") } else { returnnil } } funcBoot(r Robot)error { return r.PowerOn() } funcmain() { t := T850{ Name: "The Terminator", } r := R2D2{ Broken: true, } err := Boot(&r) if err != nil { fmt.Println(err) } else { fmt.Println("Robot is powered on") } err = Boot(&t) if err != nil { fmt.Println(err) } else { fmt.Println("Robot is powered on") } }
8. 字符串
一些基础的操作就不讲了,直接看一些我认为有意思的地方
使用缓冲区(stringBuffer)拼接字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
package main import ( "bytes" "fmt") funcmain() { var buffer bytes.Buffer for i := 0; i < 500; i++ { buffer.WriteString("z") } fmt.Println(buffer.String()) }
原理同 Java
进制表示
小写
使用 ToLower() 接口
查找
使用 strings.Index(),如果找到,则输出第一个字串的索引开始;若找不到,则输出 -1
删除字符串中的空格
删除前后空格
1 2 3 4 5 6 7 8 9
package main import ( "fmt" "strings") funcmain() { fmt.Println(strings.TrimSpace(" I don't need all the space ")) }
9. Map 相关操作
Map 是 key-value 的键值对数据结构,类似于集合的意思
创建 map (但必须分配空间)
原本逻辑上声明 map,从 Java 的角度来说没什么问题
1 2 3 4 5 6 7 8
package main import"fmt" funcmain() { var a map[int]string fmt.Println(a) }
但是这个程序,我们是不能进行赋值的,原因是并没有给此 map,也就是变量 a 分配内存空间,如果我们尝试赋值,如下语句,是会报错的
1
a[1]="Drunkbaby"
那么要如何才能分配空间并赋值呢?这里我们创建一个空的 map 需要用 make,完整有效代码如下
1 2 3 4 5 6 7 8 9 10 11 12
package main import"fmt" funcmain() { // 创建空 map,却没有分配空间 var a map[int]string // 在使用 map 前,需要先 make,make 的作用就是给 map 分配数据空间 a = make(map[int]string, 10) a[1] = "Drunkbaby;" fmt.Println(a) }