首页  

GO入门指南实例     所属分类 go 浏览量 316
变量(Variable)
var a int // 默认为0
var a int = 1 // 声明时赋值
var a = 1 // 声明时赋值
a := 1
msg := "Hello World!"


基本类型 空值 nil 整型 int(取决于操作系统), int8, int16, int32, int64, uint8, uint16, … 浮点数 float32, float64 字节 byte (等价于uint8) 字符串 string 布尔值 boolean,(true 或 false) var a int8 = 10 var c1 byte = 'a' var b float32 = 12.2 var msg = "Hello World" ok := false
字符串 str := "hello" fmt.Println(reflect.TypeOf(str).Kind()) // string fmt.Println(reflect.TypeOf(str[0]).Kind()) // uint8 fmt.Println(str[0], string(str[0])) // 104 h fmt.Printf("%d %c\n", str[0], str[0]) // 104 h fmt.Println(len(str)) // 5 str1 := "GO语言" fmt.Println(len(str1)) // 8 runeArr := []rune(str1) fmt.Println(runeArr[2], string(runeArr[2])) // 35821 语 fmt.Println(len(runeArr)) // 4 reflect.TypeOf(xxx).Kind() 获取变量类型 字符串 byte数组 一个英文字符 1个字节 ,一个中文字符 一般 3个字节 将 string 转为 rune 数组 , 字符串中的每个字符 都用 int32 表示 ,4个字节
数组(array)与切片(slice) 数组长度不可变 切片使用数组作为底层结构 可自动扩展 切片3要素 容量 长度 和 指向底层数组的指针 声明切片时可设置容量大小 ,避免频繁扩容 var arr1 [3]int // 一维 var arr2 [2][3]int // 二维 var arr3 = [3]int{1, 2, 3} fmt.Println(arr1) // [0 0 0] fmt.Println(arr2) // [[0 0 0] [0 0 0]] fmt.Println(arr3) // [1 2 3] arr4 := [3]int{2,3,4} fmt.Println(arr4) // [2 3 4] for i := 0; i < len(arr4); i++ { arr4[i] += 1 } fmt.Println(arr4) // [3 4 5] slice1 := make([]float32, 0) // 长度为0的切片 fmt.Println(slice1,len(slice1),cap(slice1)) slice2 := make([]float32, 3, 5) // [0 0 0] 长度3 容量5的切片 fmt.Println(len(slice2), cap(slice2)) // 3 5 // 添加元素,切片容量自动扩展 slice2 = append(slice2, 1, 2, 3) // [0, 0, 0, 1, 2, 3] fmt.Println(len(slice2), cap(slice2)) // 6 12 // 子切片 [start, end) sub1 := slice2[3:] // [1 2 3 ] sub2 := slice2[:3] // [0 0 0] sub3 := slice2[1:4] // [0 0 1] fmt.Println(sub1,sub2,sub3) // 合并切片 // sub2... 将切片解构为 N 个独立的元素 sub4 := append(sub1, sub2... ) // [1 2 3 0 0 0] fmt.Println(sub4)
字典 键值对 map map 类似于 java 的 HashMap,Python的字典(dict) // 仅声明 m1 := make(map[string]int) // 声明时初始化 m2 := map[string]string{ "a": "A", "b": "B", } fmt.Println(m1,m2) // map[] map[a:A b:B] // 赋值/修改 m1["a"] = 1 m2["a"] = "A2" fmt.Println(m1,m2) // map[a:1] map[a:A2 b:B]
指针(pointer) 指针 变量地址 & 获取变量地址 str := "hello" var p *string = &str 参数按值传递 函数内部 拷贝一份参数的副本,对副本的修改 不影响 原值 传递指针,直接操作指针指向的变量 func pointTest(){ str := "hello" var p *string = &str *p = "hello,go" fmt.Println(str) num := 1 // 值传递 函数内部修改的是副本 原值不变 add1(num) fmt.Println(num) // 1 // 传地址 直接修改原值 add2(&num) fmt.Println(num) // 2 } func add1(num int) { num += 1 } func add2(num *int) { *num += 1 }
流程控制(if, for, switch) type 关键字定义 新类型 没有枚举(enum) 可用常量模拟 switch 不需要 break,匹配到某个 case,默认不会继续执行 如果需要继续往下执行,使用 fallthrough for range 遍历 数组(arr) 切片(slice) 字典(map) score := 90 if score < 60 { fmt.Println("fail") } else { fmt.Println("success") } type Gender int8 const ( MALE Gender = 1 FEMALE Gender = 2 ) gender := MALE switch gender { case FEMALE: fmt.Println("female") case MALE: fmt.Println("male") default: fmt.Println("unknown") } sum := 0 i := 0 for ; i < 10; i++ { if sum > 20 { break } sum += i // fmt.Println(i, sum) } fmt.Println(i, sum) // 7 21 nums := []int{10, 20, 30} for i, num := range nums { fmt.Print(i, num, " ") } fmt.Println() m2 := map[string]string{ "a": "A", "b": "B", } for key, value := range m2 { fmt.Println(key, value) }
函数(functions) func funcName(param1 Type1, param2 Type2, ...) (return1 Type3, ...) { // body } 错误处理(error handling) os.Open 2个返回值,*File 和 error 调用成功,error 为 nil 调用失败,例如文件不存在,可通过 error 获取具体错误信息 file, err := os.Open("file_not_exist.txt") if err != nil { // open file_not_exist.txt: no such file or directory fmt.Println(err) } errorw.New 返回自定义错误 func newErrorTest() { // fmt.Println(nameCheck(nil)) fmt.Println(nameCheck("")) fmt.Println(nameCheck("xxx")) fmt.Println(nameCheck("tiger")) } func nameCheck(name string) error { if len(name) == 0 { return errors.New("name is null") } if name == "xxx" { return errors.New("name error") } fmt.Println("name=", name) return nil } 不可预知的错误,例如数组越界,导致程序非正常退出,称为 panic panic 惊恐 恐慌 Java try catch 机制 Go defer 和 recover defer 定义 异常处理的函数,退出前,执行 defer 注册的函数 如果触发了 panic,控制权 交给 defer defer 中 使用 recover,使程序恢复正常 func get(index int) (ret int) { defer func() { if r := recover(); r != nil { fmt.Println("Some error happened!", r) ret = -1 } }() arr := [3]int{1, 2, 3} return arr[index] } fmt.Println(get(0)) fmt.Println(get(7))
结构体(struct) 和 方法(methods) 结构体类似 Java中的 class,可以在结构体中定义字段和 方法,可 实例化 type Student struct { name string age int } func (student *Student) getName() string { return student.name } func (student *Student) getInfo() string { return fmt.Sprintf("name=%s,age=%d", student.name, student.age) } student := &Student{name: "tiger"} fmt.Println(student.getName()) fmt.Println(student.getInfo()) student2 := &Student{name: "cat",age:7} fmt.Println(student2.getInfo()) student3 := new(Student) student3.name="dyyx" student3.age=9 fmt.Println(student3.getInfo())
接口(interfaces) type Person interface { getName() string } 接口 定义了一组方法的集合,接口不能被实例化,一个类型可以实现多个接口 不需要显式地声明实现了哪一个接口,实现接口对应的方法即可 Student 实现了 getName 方法 ,可转为 接口类型 Person var _ Person = (*Student)(nil) 编译时检测 将空值 nil 转换为 *Student 类型,再转换为 Person 接口, 如果转换失败,说明 Student 并没有实现 Person 接口的所有方法 type Person interface { getName() string } func interfaceTest() { student := Student{name: "tiger"} // main.Student fmt.Println(reflect.TypeOf(student)) pointOfStudent := &student // *main.Student fmt.Println(reflect.TypeOf(pointOfStudent)) // 为啥这里不用 * ? var person Person = &student fmt.Println(reflect.TypeOf(person).Kind()) // ptr // *main.Student fmt.Println(reflect.TypeOf(person)) fmt.Println(person.getName()) student2 := person.(*Student) fmt.Println(student2.getName()) var student3 *Student = &student fmt.Println(student3.getName()) // 为啥这里不用 // var person2 *Person = &student var person2 Person = &student fmt.Println(person2.getName()) }
空接口 interface{} 可表示任何类型 m := make(map[string]interface{}) m["a"] = "hello" m["b"] = 3 m["c"] = [3]int{1, 2, 3} fmt.Println(m)
并发编程(goroutine) 提供 sync 和 channel 两种方式 支持协程(goroutine) 并发 并发下载 N 个资源,多个并发协程之间不需要通信,可使用 sync.WaitGroup,等待所有并发协程执行结束 sync.WaitGroup var wg sync.WaitGroup func download(url string) { fmt.Println("start to download", url) time.Sleep(time.Second) // 模拟耗时操作 // done 计数减1 wg.Done() } func waitGroupTest() { for i := 0; i < 3; i++ { // add 增加计数 wg.Add(1) go download("http://codefun007.xyz/dl/" + string(i+'0')) } wg.Wait() fmt.Println("all download Done!") }
channel var ch = make(chan string, 9) // 创建大小为 9 的缓冲信道 func downloadUseChannel(url string) { fmt.Println("start to download", url) time.Sleep(time.Second) ch <- url // 将 url 发送给信道 } func channelTest() { for i := 0; i < 3; i++ { go downloadUseChannel("http://codefun007.xyz/dl/" + string(i+'0')) } for i := 0; i < 3; i++ { msg := <-ch // 等待信道返回消息 fmt.Println("download done", msg) } fmt.Println("all download use channel Done!") }
单元测试(unit test) add.go package main func add(a int,b int) int { return a+b } add_test.go package main import "testing" func TestAdd(t *testing.T) { if result := add(1, 2); result != 3 { t.Error("add(1, 2) should be equal to 3") } } 运行指定测试方法 go test -v -run TestAdd === RUN TestAdd --- PASS: TestAdd (0.00s) PASS ok simplego 0.537s
https://gitee.com/dyyx/hellocode/blob/master/7days-golang/simpledemo/simplego/main.go
go http server go基本语法例子 go程序设计语言01_05入门之获取URL go程序设计语言01_06入门之并发获取多个URL 简洁的GO语言 GO多线程异步处理实例 go channel 实例 GO 并发递增计数实例 Go并发构建模块 Go语言atomic原子操作 GO mutex 与 atomic 性能对比 go defer 延迟函数 GO flag 命令行参数解析 GO panic recover go socket 编程 echo server GO文件读取 GO 面向对象编程 GO reflect go httpFileServer GO获取环境变量

上一篇     下一篇
go httpFileServer

temporal 任务运行机制实例测试

GO获取环境变量

temporal压测方案及记录

prometheus metrics 格式说明

httpclient 超时设置