基础语法
变量声明
go
package main
func main() {
// 变量声明(类型推导)
name := "jack"
age := 10
// 显式声明
var pi float64 = 3.14
fmt.Println(name, age, pi)
}
以下有一些常见的语法规则:
1、在 GoLang 中,:= 只能在函数内用,包级需要使用 var 显式声明。
2、未使用的变量 / import 会报错(Go 强迫写干净的代码)。
循环与判断
go
package main
func main() {
age := 10
// if 内的条件语句不需要使用 () 包围
if age > 5 {
// ...
}
// Go 只有 for 循环,没有 while 以及 do-while
for i := 0; i < 3; i++ {
// ...
}
// 类似 while 的写法
n := 3
for n < 3 {
n++
}
}
数组与切片
基础语法:
数组:[N]T切片:[]T
在 Go 中,数组的大小是固定的,不可扩容,且属于值语义。
go
package main
func main() {
// 声明数组
nums := [3]int{1, 2, 3}
// 自动推导长度
nums2 := [...]int{1, 2, 3, 4}
fmt.Println(nums) // [1 2 3]
fmt.Println(nums2) // [1 2 3 4]
// 值语义
a := [3]int {1, 1, 1}
b := a;
b[0] = 100;
fmt.Println(a) // [1 1 1]
fmt.Println(b) // [100 1 1]
}
而切片的大小是可变的,可以通过 append 增加元素,属于引用语义。
go
package main
import "fmt"
func main() {
// 声明切片
a := []int{1, 2, 3}
b := a
b[0] = 100
// 引用语义
fmt.Println(a) // [100 2 3]
fmt.Println(b) // [100 2 3]
b = append(b, 4)
b = append(b, 5, 6, 7)
fmt.Println(a) // [100 2 3]
fmt.Println(b) // [100 2 3 4 5]
}
可以通过 make 创建切片,并设置长度和容量。
go
package main
func main() {
// 可以通过 make 创建切片并设置 capacity
c := make([]int, 3, 5)
fmt.Println(c) // [0 0 0]
fmt.Println(len(c), cap(c)) // 3 5
}
Map
基础语法:
map[key]value
Map 用来表示映射关系,在 Go 中,Map 属于内置的数据类型。
go
package main
func main() {
// 字面量初始化
// 每个记录后面必须以 "," 结尾,哪怕是最后一项
scores := map[string]int {
"小明": 90,
"小玉": 99,
}
fmt.Println(scores["小明"])
// 判断 Map 中是否存在某个元素
score, ok := scores["小青"]
if !ok {
fmt.Println("小青不存在")
}
// 增加元素
scores["小青"] = 100
// 删除元素(删除不存在的不会报错)
delete(scores, "小青")
// 遍历 Map
for k, v := range scores {
fmt.Println(k, v)
}
}
函数、结构体与指针
函数
GoLang 的函数支持多返回值,函数可以作为参数传递,没有默认参数,没有函数重载。
go
// 定义一个最基本的函数
func 函数名(参数) 返回值类型 {
}
// add 函数
func add(a int, b int) int {
return a + b
}
// 参数类型相同可以简写
func add(a, b int) int {
return a + b;
}
// Go 支持多返回值(这是很常用的特性)
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("除数不能为0")
}
return a / b, nil
}
指针
GoLang 中也有指针,但是比 C++ / C 的简单很多,不需要自己手动管理内存。
bash
x := 10
p := &x // p 是指向 x 的指针,& 进行取地址
*p = 20
fmt.Println(x) // 20
结构体
GoLang 没有 class,用 struct 代替。
go
// 定义结构体
type Server struct {
Name string
IP string
Port string
Running bool
}
// 创建实例
s := Server{
Name: "web-01",
IP: "192.168.1.1",
Port: 8080,
Running: true,
}
// 访问字段
fmt.Println(s.Name, s.Port)
方法是绑在结构体上的函数,GoLang 拥有两个新增的概念
- 值接收者
- 指针接收者
两个接收者的区别在于其定义的函数能不能修改结构体内的字段。
go
// 值接收者(不修改原结构体)
func (s Server) Status() string {
if s.Running {
return s.Name + " is running"
}
return s.Name + " is stopped"
}
// 指针接收者(可以修改结构体)
func (s *Server) Stop() {
s.Running = false
}
// 调用
s.Stop()
fmt.Println(s.Status()) // web-01 is stopped
需要修改结构体字段时用指针接收者
*Server,只读用值接收者Server