跟Java比力学习。
hello word
示例代码
- test1.go文件:
- // 包路径
- package main
- // 导入模块,下面两种都行
- import (
- "fmt"
- )
- import "log"
- // main方法
- func main() {
- log.Print("hello word !!!")
- fmt.Print("hello word 222")
- }
复制代码 运行命令
go run .\test1.go
打包二进制
> go build .\test1.go
./test1.exe
变量可见性
首字母大写就是public
首字母小写就是private
{不能单独一行
在Java和C中都可以,go中就不行
正确的应该这样:
行结束不需要分号;
加上后IDE会自动给删除
如果你就是要将两行代码放在一行,则需要在结尾加上;分号,但IDEA会在生存的时间自动给你拆分为两行。
字符串
字符串毗连+
格式化
- // 格式化String.format
- value := fmt.Sprintf("%s - %s", ">>", "<<")
- // 打印到console上
- fmt.Print(value)
- // 合并:格式化并打印出
- fmt.Printf("%s - %s\n", ">>", "<<")
复制代码 变量
变量申明和赋值
- // 只声明一个变量i
- var i int
- // 给i变量赋值2
- i = 2
- // 创建变量并赋值3
- ii := 3
- // 声明常量
- const pi float64 = 3.14
- var bo bool = false
- bo1 := false
- var f1 float32 = 1.1
- var f2 = 1.2
- f3 := 1.3
复制代码 平凡变量范例
uint8 unsiged int 8位
int8 有符号8位int
int16,int32,int64 类似,没有long
float32、float64 轻易明白,没有double
这两个不清晰:
complex64 32 位实数和虚数
complex128 64 位实数和虚数
不一样的:
uintptr 无符号整型,用于存放一个指针
rune 类似 int32
byte 类似 uint8 0到255
变量作用域
全局变量和局部变量可以名称一致,但使用时会优先使用局部变量。
数组
一维数组
- var strs = [3]string{"111", "222", "333"}
- // 初始化数组中 {} 中的元素个数不能大于 [] 中的数字。 多出就会报错
- var strs = [3]string{"111", "222", "333","444"}
- // 只初始化了前两个元素
- var strs = [3]string{"111", "222"}
- // 数组长度根据后边初始化数据的个数来确定为2
- var strs = [...]string{"111", "222"}
- // 初始化指定元素下表元素的数据
- var strs = [...]string{1: "111", 4: "222"}
- // 数组的长度
- var length int = len(strs)
- fmt.Println("数组长度:", length)
- for i := 0; i < length; i++ {
- // 访问和给数组赋值
- fmt.Println(len(strs[i]))
- strs[i] = "ab"
- }
复制代码 二维数组
- // 定义二位数组,并初始化
- var rows = [][]int{
- {1, 2, 3}, {4, 5, 6}, {7, 8, 9},
- }
- fmt.Println(rows)
- // 二位数组一行一行添加
- // [3][3]int{} 错误,行列取悦于append了多少次
- var rows1 = [][]int{}
- var row1 = []int{1, 2, 3}
- var row2 = []int{4, 5, 6}
- // 各行可以一样,也可不一样长
- var row3 = []int{7, 8, 9, 10}
- rows1 = append(rows1, row1)
- rows1 = append(rows1, row2)
- rows1 = append(rows1, row3)
- fmt.Println(rows1)
- fmt.Println("row count:", len(rows1))
- fmt.Println("col count:", len(row1))
- fmt.Println("row1 :", rows[0])
- fmt.Println("row2 :", rows[1])
- // 不允许访问列 rows[][1] syntax error: unexpected ], expected operand
- // fmt.Println("col1 :", rows[][1])
- fmt.Println("cell[1][1] :", rows[1][1])
- // 遍历二维数组
- for i := 0; i < len(rows1); i++ {
- for j := 0; j < len(rows1[i]); j++ {
- fmt.Println("cell[", i, "][", j, "] : ", rows1[i][j])
- }
- }
复制代码 方法参数传数组和传指针
- // 包路径
- package main
- import "fmt"
- // main方法
- func main() {
-
- // 定义二位数组,并初始化
- var rows = [][]int{
- {1, 2, 3}, {4, 5, 6}, {7, 8, 9},
- }
- fmt.Println(rows)
- addRow(rows)
- fmt.Println(rows)
-
- // 传递二维数组的指针 &rows
- addRow1(&rows)
- fmt.Println(rows)
-
- // 调用固定元素数组参数,必须是固定元素个数数组
- // 数量不一致直接报错
- row1 := [5]int{1, 2, 3, 4, 5}
- printRow(row1)
-
- // 将二维数组的第一行当做一维数组也不行
- // printRow(rows[0])
- }
- // 数组是值类型,这么传实际传的是值而非引用
- func addRow(rows [][]int) {
- row := []int{11, 22}
- rows = append(rows, row)
- }
- // 接受一个二位数组的指针,就是地址
- func addRow1(rows *[][]int) {
- row := []int{11, 22}
- *rows = append(*rows, row)
- }
- // 必须这么调用:row1 := [5]int{1, 2, 3, 4, 5}; printRow(row1)
- func printRow(row [5]int) {
- fmt.Println(row)
- }
复制代码 指针数组
- // 定义指向数组的指针数组
- ptr := []*int{&rows[0], &rows[1], &rows[2]}
复制代码 指向指针的指针
- var pptr **int
- 已经很熟悉了,不用再说了。
复制代码 结构体
基本语法
- // 包路径
- package main
- import "fmt"
- // Book 全局可以使用
- type Book struct {
- title string
- auth string
- }
- // main方法
- func main() {
- // 定义结构体,只能在方法里边用
- /*type Book struct {
- title string
- auth string
- }*/
-
- var book1 Book
- book1 = Book{"title1", "auth2"}
- book1 = Book{title: "title2"}
- // book2 获取book1的值,最后那个也添加了个逗号,恶心不
- book2 := Book{
- title: book1.title,
- auth: book1.auth,
- }
- book1.auth = "1000"
-
- // 传值:不会修改值
- setAuth200(book2)
-
- // 传地址:会修改值
- setAuth200Point(&book2)
-
- var book3 Book
- // 没有book3 == nil 和 book3 == null这么一说
- // 是空对象相当于java中:book3 = new Book(); 不给里边赋值,所以直接访问不报错
- fmt.Println(book3)
- book3.auth = "2000"
- }
- // 真NM耐造,book为null 不会报错
- func setAuth200(book Book) {
- book.auth = "2000"
- }
- func setAuth200Point(bookPtr *Book) {
- (*bookPtr).auth = "2000"
- }
复制代码 继承和匿名字段
- type Person struct {
- name string
- sex string
- age int
- }
- func (p *Person) say() {
- fmt.Println("person fun11")
- }
- type Student struct {
- // 将Person中的属性继承过来 s1.sex
- Person
- // 创建person属性 s1.person.sex
- person Person
- id int
- addr string
- // 如果出现重名情况
- age int
- // 匿名字段
- string
- }
- // 继承和匿名字段
- func main() {
- fmt.Println("main ...")
- s1 := Student{Person{"5lmh", "man", 20}, Person{"5lmh", "man", 20}, 1, "bj", 20, "匿名字段"}
- fmt.Println(s1)
- // 获取person属性的sex值
- fmt.Println(s1.person.sex)
- // 获取继承过来的person属性sex
- fmt.Println(s1.sex)
- fmt.Println(s1.Person.sex)
- // 如果父子类中的属性重复
- // 给父类Person中赋值
- s1.Person.age = 100
- // 给子类属性age赋值
- s1.age = 200
- fmt.Println(s1)
- // 继承还可以继承方法
- s1.say()
- fmt.Println("success ...")
- }
复制代码 切片Slice
类似java的ArrayList
- var arr = []int{1, 2, 3, 4, 5}
- fmt.Println(arr)
- // 切片类似:数组的 substring,前后是包含关系
- sp := arr[0:]
- fmt.Println(sp)
- fmt.Println(len(sp))
- fmt.Println(cap(sp))
- // 使用mark创建
- var number = make([]int, 3, 5)
- fmt.Println(number, len(number), cap(number))
- // 在3个元素后边添加
- number = append(number, 5)
- // out: [0 0 0 5] 4 5
- fmt.Println(number, len(number), cap(number))
- number = append(number, 6)
- number = append(number, 7)
- number = append(number, 8)
- // 长度超过容量后会自动扩容,二倍扩容
- number = append(number, 9)
- number = append(number, 10)
- //out:[0 0 0 5 6 7 8 9 10] 9 10
- fmt.Println(number, len(number), cap(number))
- var number1 = make([]int, len(number)*2, cap(number)*2)
- copy(number1, number)
- // out:[0 0 0 5 6 7 8 9 10 0 0 0 0 0 0 0 0 0] 18 20
- // len内的数据会默认给0
- fmt.Println(number1, len(number1), cap(number1))
- // 将里边的数据全部清理为0
- clear(number1)
- // out:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 18 20
- fmt.Println(number1, len(number1), cap(number1))
复制代码 语言范围Rang
rang 类似 java中的 迭代器 foreach
数组
- // 遍历数组,index是下标
- intArr := []int{1, 2, 3, 4, 5}
- for index := range intArr {
- fmt.Print(index, "=", intArr[index], " ")
- }
- fmt.Println("")
- // 可以直接将value遍历出来
- for index, value := range intArr {
- fmt.Print(index, "=", value, " ")
- }
- fmt.Println("")
- // 如果不需要index则可以用_替代,否则由会给你报错,这个变量没用
- for _, value := range intArr {
- fmt.Print(value, " ")
- }
复制代码 Map
- // map的遍历
- fmt.Println("")
- map1 := make(map[int]string, 3)
- fmt.Println(map1)
- map1[10] = "aa"
- map1[11] = "bb"
- fmt.Println(map1)
- // 遍历map,当前key和value如果不用,可以用_替代
- for key, value := range map1 {
- fmt.Println(key, ":", value)
- }
- // 如果只有一个同样,遍历的是key,类似数组的index
- for key := range map1 {
- fmt.Println(key)
- }
复制代码 切片
- fmt.Println("")
- // 切片也可以类似
- spArr := make([]int, 2, 50)
- copy(spArr, intArr[3:])
- // out:[4 5]
- fmt.Println(spArr)
- for index := range spArr {
- fmt.Print(index, "=", intArr[index], " ")
- }
复制代码 channel
- // channel 看样子类似java中的MQ,但不用那么复杂的实现机制
- // chan int : 首先这个是一个通道channel, 然后是一个装int的channel
- // 类似:LinkedQuery<Integer>
- ch := make(chan int, 10)
- ch <- 11
- ch <- 12
- ch <- 1000
- for val := range ch {
- fmt.Print(val, " ")
- // 一边遍历,一边可以添加数据,比ArrayList的强多了
- // 但这么搞就死循环了,逻辑上注意
- // ch <- 1000
- }
- // 最后需要关闭
- close(ch)
复制代码 Map聚集
- // 创建 <int,string> 初始容量为2
- mapCap := 2
- map1 := make(map[int]string, mapCap)
- fmt.Println(map1)
- // 添加元素,可相同会覆盖
- map1[11] = "bb"
- fmt.Println(map1)
- map1[11] = "bbb"
- map1[22] = "ccc"
- map1[33] = "ddd"
- fmt.Println(map1)
- // 根据Key删除元素
- fmt.Println(len(map1))
- delete(map1, 22)
- fmt.Println(map1)
- fmt.Println(len(map1))
- // 获取元素,如果没有则为空
- fmt.Println("key:", 11, ",value:", map1[11])
- fmt.Println("key:", 66, ",value:", map1[66])
- // 如果有值则 value就是值,hasBollen为true,如果没有值 hasBollen = false
- value, hasBollen := map1[66]
- if hasBollen {
- fmt.Println("数据存在,value:", value)
- } else {
- fmt.Println("数据不存在,key:", 66)
- }
- // 遍历map
- fmt.Println(map1)
- for key, value := range map1 {
- fmt.Println("key:", key, ",value:", value)
- }
复制代码 方法
匿名方法
- func(i int, wg *sync.WaitGroup)为形参
- (i, &wg) 为实际参数
- var wg sync.WaitGroup
- for i := 0; i < 10; i++ {
- wg.Add(1)
- go func(i int, wg *sync.WaitGroup) {
- fmt.Println(i)
- time.Sleep(20 * time.Microsecond)
- wg.Done()
- }(i, &wg)
- }
- wg.Wait()
复制代码 接口Interface
差别点:
1. struct 实现 interface,并没有显着的实现写法,各写各的
2. struct 可以实现部分interface的方法,而不必要全部实现。直接用没问题,用interface举行引用就报错:
- // 包路径
- package main
- import "fmt"
- // 接口有两个方法
- type Animal interface {
- call()
- getName() string
- }
- // 创建类Market,有一个name熟悉
- type Market struct {
- name string
- }
- /**
- 实现方法:
- 1. (m Market): 标识 这个是Market类的方法
- 2. call() 接口的方法
- */
- func (m Market) call() {
- fmt.Println("market call,", "name:", m.name)
- }
- func (m Market) getName() string {
- return m.name
- }
- type Tiger struct {
- name string
- }
- func (t Tiger) call() {
- fmt.Println("tiger call,", "name:", t.name)
- }
- func (t Tiger) getName() string {
- return t.name
- }
- func animalCall(a Animal) {
- a.call()
- }
- // 空接口,可以接受任何类型的对象,并根据类型判断
- func print(v interface{}) {
- switch t := v.(type) {
- case int:
- fmt.Println("integer", t)
- case string:
- fmt.Println("string", t)
- }
- }
- // main方法
- func main() {
-
- // 接口 interface
- m1 := Market{name: "m111"}
- fmt.Println(m1.getName())
- m1.call()
-
- m2 := new(Market)
- m2.name = "m222"
- m2.call()
-
- t1 := Tiger{name: "t1111"}
- fmt.Println(t1.getName())
- t1.call()
-
- // 根据传值的不同
- animalCall(m1)
- animalCall(t1)
-
- // 定义一个接口,然后复制类对象,按照接口调用就可以
- var a1 Animal
- a1 = m1
- a1.call()
-
- // 将m1转换为 Market类型
- m11 := a1.(Market)
- fmt.Println(m11.name)
-
- // 空接口接受人任何对象
- print(11)
- print("str11")
-
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |