go语言号称better c,同时兼具c的运行效率和php的开发效率,对于后端程序员可兼顾开发效率和运行效率,在WEB/中间件/容器化/虚拟货币上都有较为广泛的应用。
go基础语法
- go语言的基础语法,go的语法很灵活
- 和java相同基础类型有bool, byte, int8, int16, int32, rune, float32, float64,
- 除此以外还有int,int64,complex,uintptr(存储指针),string(初始值为""),array,struct(结构体,和c一脉相承),function,interface等类型
- 引用类型包括: map,slice,channel
var x = "xx" // 全局变量
func defVar() {
// 定义变量有2种方式
var a = "123"
var a0 int // go语句结尾不用写封号
b, c := "4", "5"
// go语言中不允许定义了变量而不使用,否则编译不通过
fmt.Println(a, a0, b, c)
// 常量可以定义而不使用
const d = "cc"
println(&x, x)
x := "yy"
println(&x, x)
{
// 不同作用域可重新定义变量
b, c := "6", "7"
fmt.Println(b, c)
}
// 对err进行退化赋值处理
f, err := os.Open("/opt/file/test.txt")
buf := make([]byte, 1024)
n, err := f.Read(buf)
println(err, n)
}
func defReference() {
// 数组定义(第一次看到时语法有点不太能接受)
s := []int{1, 2, 3, 4}
s = append(s, 5)
// 切片语法和python完全一样
fmt.Println(s[1:])
// map的语法
m := make(map[string]int)
m["a"] = 1
// 判断map是否包含某个元素
if _, ok := m["b"]; ok {
// do nothing
} else {
m["b"] = 2
}
fmt.Println(m)
}
/**
* go语言中为啥要保留struct这个结构体呢,有点不太明白,数据结构java中一般都是定义个class解决的
*
*/
func defType() {
type (
user struct {
name string
age uint8
}
event func(string) bool
)
u := user{"tom", 20}
fmt.Println(u)
var f event = func(s string) bool {
println(s)
return s != ""
}
f("abc")
}
func main() {
//defVar()
defReference()
defType()
}go函数
- go的25个关键字如下:
- break,default,func,interface,select,case,defer,go,map,struct,chan,else,goto,package,switch,const,fallthrough,if,range,type,continue,for,import,return,var
- 其中与java有差异的func方法/select(信道)/fallthrough(控制语句) map/struct/const/range/var(变量和数据) defer(延迟)/go(协程)/chan()
import (
"errors"
"fmt"
"runtime/debug"
)
func defIncrement() {
a := 1
//++a // 前置的方式go取消了
a++
p := &a // 将a的地址赋给p
*p++ // 类似于c的指针操作语法
fmt.Println(a)
/**
* & 取地址运算符 - 用于获取对象地址
* * 指针运算符 - 间接引用目标对象
* **T 二级指针
*/
}
func defInit() {
// 定义一个结构体数据类型
type student struct {
name string
height int
age int
}
// 使用花挂号来初始化结构体
var joey student = student{"joey", 120, 5}
judy := student{"judy", 115, 5}
fmt.Println(joey)
fmt.Println(judy)
}
func defArr() {
// array定义 []int{} 这种方式
c := []int{1, 2, 3}
d := []int{1, 2, 3, 4, 5}
fmt.Println(c, d)
}
func defIf() {
// if-else if-else 流程和Java一样,只是可省略括号
var age int = 6
if age < 7 {
fmt.Println("学龄前")
} else if 7 <= age && age < 13 {
fmt.Println("小学生")
} else {
fmt.Println("其他")
}
if age++; age >= 7 {
fmt.Println("小学生及以上")
}
// go语言不支持以下的三元运算符
//a := (age>=7 ? "":"")
//省略: go的switch和其他语言的差异在于只要case执行成功就不会执行后面的语句,只有case全失败才会执行default,更符合普通使用的判断场景[备注:fallthrough强制进入下一个判断流程],不过我推测应该使用的很少,省略这部分
}
func defFor() {
// go中只有for循环,没有while和do-while.
for i := 0; i < 3; i++ { // 普通的for循环
fmt.Println(i)
}
x := 0
for x < 10 { // 类似于while(x<10){}
x++
}
for { // while(true){}
break
}
// for range
data := []string{"a", "b", "c"}
for i, s := range data {
fmt.Println(i, s)
if i == 0 {
data[0] = "b"
}
}
// range会复制目标数据,循环时数组发生变化变量不变
m := [3]int{10, 20, 30}
for i, x := range m {
if i == 0 {
m[0] += 100
m[1] += 200
m[2] += 300
}
//x: 10,data: 110
//x: 20,data: 220
//x: 30,data: 330
fmt.Printf("x: %d,data: %d\n", x, m[i])
}
}
// func不支持嵌套
func add(x, y int) int {
return x + y
}
func exec(f func(x, y int) int, x int, y int) int {
return f(x, y)
}
// 指针是go与其他语言最显著的区别
func testPointer() *int{
a := 10
return &a
}
// 匿名函数, 和js基本一样
func testAnonymous(){
func(s string){
fmt.Println(s)
}("test it")
add := func(x, y int) int {
return x+y
}
fmt.Println(add(1,2))
}
// 闭包closure,defer todo:暂时省略
// 错误处理 error handle
// 此处的error为官方接口
func div(x, y int)(int, error){
if y == 0{
return 0, errors.New("divide by zero")
}
return x/y, nil
}
// panic-recover-类似于try...catch...,但是感觉比try catch难用很多
func testPanic(){
defer func(){
if err:=recover();err!=nil{
debug.PrintStack()
}
}()
panic("holy shit")
// 下面这句执行不到了
fmt.Println("test shit")
}
func main() {
defIncrement()
defInit()
defArr()
defIf()
defFor()
fmt.Println(exec(add, 1, 2))
testAnonymous()
res,err := div(1,0)
fmt.Println(res, err)
testPanic()
}
数据类型
数据类型:包含array,slice,map,struct
func defStruct(){ // 定义了一个会员,包含name/age/idNo/mobileNo/registerDate字段 type Member struct{ name string age int idNo string mobileNo string registerDate string } zhangsan := Member{"Zhang San",20,"310xxxxxx","+86-11111111111","2022-03-15 10:10"} fmt.Println(zhangsan) var lisi Member lisi.name = "Li Si" lisi.age = 21 lisi.idNo = "333xxxxxx" lisi.mobileNo = "+86-1234567890" lisi.registerDate = "2022-05-15 00:00" fmt.Println(lisi) // 定义struct指针 var zhangsanCopy *Member zhangsanCopy = &zhangsan fmt.Println(zhangsanCopy) } // 切片-slice和python中的类似,string/数组使用[:]这种格式 func defSlice(){ var nums [] int fmt.Println(nums, len(nums), cap(nums)) nums = append(nums, 0) nums = append(nums, 1) nums = append(nums, 2) nums = append(nums, 3,4) /* 创建切片 numbers1 是之前切片的两倍容量*/ nums2 := make([]int, len(nums), (cap(nums))*2) //复制数组nums熬nums2 copy(nums2,nums) fmt.Println(nums2, len(nums2), cap(nums2)) } // map和python中的基本一致 func defMap(){ // 初始化方式1: map初始化为nil var memberIdMap map[string]string memberIdMap = make(map[string]string) memberIdMap["zhangsan"] = "310xxxxxx" memberIdMap["lisi"] = "333xxxxxx" fmt.Println(memberIdMap) // 初始化方式2 testMap := map[string]string{"a":"1","b":"2","c":"3"} for key:= range testMap{ fmt.Println(key, testMap[key]) } // 删除元素 delete(testMap, "a") } func main(){ defStruct() defSlice() defMap() }并发
*
测试
*