Go Roadmap-Basics
地址:https://roadmap.sh/golang
简介:Github star No.6 学习路线 Go 中译版
Learn the Basics
Go特点:静态类型,运行速度快,编译语言,编译速度快,自动垃圾回收,没有类和对象,没有继承关系。
example:
package main
import ("fmt")func main() {fmt.Println("Hello World!")
}
Basic Syntax
基本语法:包申明、导包、函数、语句。
上面的代码块讲解:
- 属于main包
- 导入了fmt这个包
- 空行更可读
- func main(){}是函数
- fmt.Println()是fmt包里的函数,可以打印文字。
基本语句:fmt.Println("Hello World!")
敲击enter键就可以结束一行(不用;)
所以:“{”不可以在一行的开头
Variables in Go
最常用变量类型:int float32 string bool
创建变量:
- 用var关键字
var name type = value//不加tpye也可以推断
- 用:=标志
name := value
tips:“:=”和auto类似,不分配值的时候不能用。
并且只能在函数内使用。var可以在函数外面。
变量的自动初始化:
string初始为“”
int初始为0
bool初始为false
Data Types
package main
import ("fmt")func main() {var a bool = true // Booleanvar b int = 5 // Integervar c float32 = 3.14 // Floating point numbervar d string = "Hi!" // Stringfmt.Println("Boolean: ", a)fmt.Println("Integer: ", b)fmt.Println("Float: ", c)fmt.Println("String: ", d)
}
For Loop
go只有一种循环体,就是for循环。
三内容循环:
sum := 0
for i := 1; i < 5; i++ {sum += i
}
fmt.Println(sum) // 10 (1+2+3+4)
区别在于:没有() 没有int 用的是:=。
while循环:
n := 1
for n < 5 {n *= 2
}
fmt.Println(n) // 8 (1*2*2*2)
无限循环:(没有终止条件)
sum := 0
for {sum++ // repeated forever
}
fmt.Println(sum) // never reached
For-each range循环:
strings := []string{"hello", "world"}
for i, s := range strings {fmt.Println(i, s)
}
0 hello
1 world
String iteration: runes or bytes:
for i, ch := range "日本語" {fmt.Printf("%#U starts at byte position %d\n", ch, i)
}
U+65E5 '日' starts at byte position 0
U+672C '本' starts at byte position 3
U+8A9E '語' starts at byte position 6
Range
在For Loop中
Conditional Statements
if
if / else
switch case
x := trueif x {fmt.Println(s)}
if x == 100 {fmt.Println("Japan")} else {fmt.Println("Canada")}
if x == 50 {fmt.Println("Germany")} else if x == 100 {fmt.Println("Japan")} else {fmt.Println("Canada")}
Errors/Panic/Recover
go不靠stack traces,也不靠try/catch
而是靠函数的值返回,和其他数据类型一样。
Conditional Statements
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")}
Functions
问题引入:
定义和声明
返回名
多返回类型
不同的函数类型
函数是为解决特定问题的封装。
有个输入给个输出。
package main
import "fmt"func SimpleFunction() {fmt.Println("Hello World")
}func main() {SimpleFunction()
}
带参数函数:
package main
import "fmt"func add(x int, y int) {total := 0total = x + yfmt.Println(total)
}func main() {// Passing argumentsadd(20, 30)
}
带返回值函数:
package main
import "fmt"func add(x int, y int) int {total := 0total = x + yreturn total
}func main() {// Accepting return value in varaiblesum := add(20, 30)fmt.Println(sum)
}
return返回值可以不写特定变量。
return返回值可以是多值,直接写return就可以。
传地址给函数:
package main
import "fmt"func update(a *int, t *string) {*a = *a + 5 // defrencing pointer address*t = *t + " Doe" // defrencing pointer addressreturn
}func main() {var age = 20var text = "John"fmt.Println("Before:", text, age)update(&age, &text)fmt.Println("After :", text, age)
}Output
Before: John 20
After : John Doe 25
匿名函数:
匿名函数就是没有函数名的函数。
Packages
包就是Go最强大的部分
fmt Package math Package string Package
fmt:
print就是输出完不换行,println就是输出完换行。
scanf和printf和C一样,还得指定%d
math:
sqrt是开根号
cbrt是开三次根
func main() {// find the square rootfmt.Println(math.Sqrt(25)) // 5// find the cube rootfmt.Println(math.Cbrt(27)) // 3// find the maximum numberfmt.Println(math.Max(21, 18)) // 21// find the minimum numberfmt.Println(math.Min(21, 18)) // 18// find the remainderfmt.Println(math.Mod(5, 2)) // 1
}
strings:
在这里插入代码片
package main
import ("fmt""strings")
func main() {lower := strings.ToLower("GOLANG STRINGS")fmt.Println(lower)upper := strings.ToUpper("golang strings")fmt.Println(upper)stringArray := []string{"I love", "Go Programming"}joinedString := strings.Join(stringArray, " ");fmt.Println(joinedString)}
Outputgolang strings
GOLANG STRINGS
I love Go Programming
Type Casting
转化一个类型到另一个类型
i := int(32.987) // 转化到int类型
Go并不支持隐式类型转换(不同于C++)
并且从string转化为int时,可以用strconv包
package main
import ("fmt""strconv"
)
func main() {var s string = "42"v, _ := strconv.Atoi(s) // convert string to intfmt.Println(v) // 42var i int = 42str := strconv.Itoa(i) // convert int to stringfmt.Println(str) // 42
}
Type Inference
尽管时静态类型,却不需要全都初始化定义的变量,
可以自动推断,通过右边的值。
package main
import "fmt"
func main() {// Multiple variable declarations with inferred typesvar firstName, lastName, age, salary = "John", "Maxwell", 28, 50000.0fmt.Printf("firstName: %T, lastName: %T, age: %T, salary: %T\n", firstName, lastName, age, salary)
}# Output
firstName: string, lastName: string, age: int, salary: float64
如果在函数体内,最好还用;=
package main
import "fmt"
func main() {name := "Rajeev Singh"age, salary, isProgrammer := 35, 50000.0, truefmt.Println(name, age, salary, isProgrammer)
}# Output
Rajeev Singh 35 50000 true
Arrays
就是一组相同元素的集合。
package main
import "fmt"func main() {var a [2]stringa[0] = "Hello"a[1] = "World"fmt.Println(a[0], a[1])fmt.Println(a)primes := [6]int{2, 3, 5, 7, 11, 13}fmt.Println(primes)
}
Hello World
[Hello World]
[2 3 5 7 11 13]
Slices
类似于arrays,但是更强大,更灵活。
也是存储多个类型相同的值。
但是slice的长度可以生长和缩小。(形象)
语法:
myslice := []int{}
上述这就是0长度,0容量的slice。
也可以初始化:
myslice := []int{1,2,3}
怎么得到长度和容量呢?
用如下两个函数:len()和cap()
myslice2 := []string{"Go", "Slices", "Are", "Powerful"}fmt.Println(len(myslice2))fmt.Println(cap(myslice2))fmt.Println(myslice2)
上述的len就是4,而cap也是4。
怎么从一个数组创建slice呢?
package main
import ("fmt")func main() {arr1 := [6]int{10, 11, 12, 13, 14,15}myslice := arr1[2:4]fmt.Printf("myslice = %v\n", myslice)fmt.Printf("length = %d\n", len(myslice))fmt.Printf("capacity = %d\n", cap(myslice))
}
Result:myslice = [12 13]
length = 2
capacity = 4
解释:【2:4】指的是左闭右开区间的,所以就是要索引为2和3的数组中的数字,所以长度是2,但是因为切隔切了从2开始后面所有的,所以容量是4。
也可以用make()函数来创建slice:
myslice1 := make([]int, 5, 10)fmt.Printf("myslice1 = %v\n", myslice1)fmt.Printf("length = %d\n", len(myslice1))fmt.Printf("capacity = %d\n", cap(myslice1))
Maps
maps是用于存放键值对组合的,无序。
map的默认值是nil。
package main
import ("fmt")func main() {var a = map[string]string{"brand": "Ford", "model": "Mustang", "year": "1964"}b := map[string]int{"Oslo": 1, "Bergen": 2, "Trondheim": 3, "Stavanger": 4}fmt.Printf("a\t%v\n", a)fmt.Printf("b\t%v\n", b)
}Result:a map[brand:Ford model:Mustang year:1964]
b map[Bergen:2 Oslo:1 Stavanger:4 Trondheim:3]
也可以用make()函数创建map
package main
import ("fmt")func main() {var a = make(map[string]string) // The map is empty nowa["brand"] = "Ford"a["model"] = "Mustang"a["year"] = "1964"// a is no longer emptyb := make(map[string]int)b["Oslo"] = 1b["Bergen"] = 2b["Trondheim"] = 3b["Stavanger"] = 4fmt.Printf("a\t%v\n", a)fmt.Printf("b\t%v\n", b)
}
想写一个空map,就是得用make()函数。
其他的var 或者:=会导致运行错误。
package main
import ("fmt")func main() {var a = make(map[string]string)var b map[string]string fmt.Println(a == nil)fmt.Println(b == nil)
}Result:false
true
map可以用什么类型的数据做键呢?
Booleans
Numbers
Strings
Arrays
Pointers
Structs Interfaces (as long as the dynamic type supports equality)
获取map元素:
map_name[key]
更新、添加map元素:
和创建是一样的。
删除map元素:
delete(map_name, key)
查找特定元素:
package main
import ("fmt")func main() {var a = map[string]string{"brand": "Ford", "model": "Mustang", "year": "1964", "day":""}val1, ok1 := a["brand"] // Checking for existing key and its valueval2, ok2 := a["color"] // Checking for non-existing key and its valueval3, ok3 := a["day"] // Checking for existing key and its value_, ok4 := a["model"] // Only checking for existing key and not its valuefmt.Println(val1, ok1)fmt.Println(val2, ok2)fmt.Println(val3, ok3)fmt.Println(ok4)
}
Result:Ford true false true
true
maps are references(类似于return by references)
如果两个map都是同一个哈希表,那么修改一个,另一个也会变。
迭代输出maps元素:
用range
来迭代输出,但是是无序的。因为maos本身是无序的数据结构。
package main
import ("fmt")func main() {a := map[string]int{"one": 1, "two": 2, "three": 3, "four": 4}for k, v := range a {fmt.Printf("%v : %v, ", k, v)}
}Result:
two : 2, three : 3, four : 4, one : 1,
如果想要有序,也可以的,使用如下的方式:
package main
import ("fmt")func main() {a := map[string]int{"one": 1, "two": 2, "three": 3, "four": 4}var b []string // defining the orderb = append(b, "one", "two", "three", "four")for k, v := range a { // loop with no orderfmt.Printf("%v : %v, ", k, v)}fmt.Println()for _, element := range b { // loop with the defined orderfmt.Printf("%v : %v, ", element, a[element])}
}Result:
two : 2, three : 3, four : 4, one : 1,
one : 1, two : 2, three : 3, four : 4,
make
make()函数可以创建、初始化slices,
maps、channels。
var intSlice = make([]int, 10) // when length and capacity is same
var strSlice = make([]string, 10, 20) // when length and capacity is different
var employee = make(map[string]int)employee["Mark"] = 10employee["Sandy"] = 20
make()函数创建channels:
channels是goroutines相互通信的中间件。
goroutines可以并发,相互之间要通信,共享资源。
package main
import "fmt"func main() {// create channel of integer typenumber := make(chan int)// access type and value of channelfmt.Printf("Channel Type: %T\n", number)fmt.Printf("Channel Value: %v", number)}Output
Channel Type: chan int
Channel Value: 0xc00007a060
structs
用户自定义类型,就是类似C++的struct
go语言没有继承,没有super
上图是structs使用。