Golang - 基础语法(相较于Java的特殊之处

37 阅读2分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

  1. 常量声明

    // iota 被调用就自增
    // const() 中未指定则默认使用 同种规则 进行赋值
    const (
    	b = "100"
    	c // = "100"
    )
    
    const (
    	i=1<<iota // 1<<0 = 1
    	j=3<<iota // 3<<1 = 6
    	k // 3<<2 = 12
    	l // 3<<3 = 24
    )
    
  2. 编写时一行语句中末尾无需 ;,若一行多句语句,则需用;断开

  3. := 解构符号,只能用于函数体内

  4. _ 空白符号 代表未使用的变量

  5. v -- equals v -= 1,是语句有返回值,规减号只能在变量名后面!

  6. a.(type) 仅能在 switch 中用,返回Type

  7. & 取变量地址 *取变量地址上的值

  8. 数组:var array[3] int; array[0] = 1 / array = [3]int{0, 1, 2}

  9. ptr := &array 可拿到地址索引

    • c: *(ptr+1) == array[1]
    • go: ptr[1] == array[1](关于go操作数组地址的疑问可以看我提出的问题[点击跳转]
  10. slice 可变长数组(切片) <=> ArrayList

    • :=[] 解构为 index: value 的键值对,默认返回value(map默认key
    • :=map[key] 解构为 value: contains
  11. 类型转换 type(value) 类似py

  12. go 关键字开启运行期携程 goroutine,同一个程序中所有的 goroutine 共享一个地址空间

  13. chan

    • 不设缓冲区时,需同步接收,否则报错 fatal error: all goroutines are asleep - deadlock!
    • 设置缓冲区时,类似IO流,(缓冲区满后)长时间阻塞仍报错 ↑
    • close() 关闭通道
  14. 结构体的方法绑定

    type Person struct {
    	name string
    	age int
    }
    
    // 方法声明结构体即可自动绑定
    func (p Person) say() {
    	println("Hello " + p.name)
    }
    
  15. 接口

    // 方法接口
    type ToString interface {
    	toString() string
    }
    
    // 接口方法需绑定结构体
    // 实现方法即为实现接口
    func (object Object) toString() string {
    	return fmt.Sprintf("%s", &object)
    }
    
  16. 异常

    // 异常为定义在 builtin.go 中的 error 接口
    // 实现 error 接口即为实现接口中定义的 Error() string 方法
    func (object Object) Error() string {
    	return fmt.Sprintf("Some errors occurred in %s and sub struct does not override this method!", object.toString())
    }
    
  17. 面向对象综合运用 - 仿 Object 类设计

    package main
    
    import "fmt"
    
    // 方法接口
    type ToString interface {
    	toString() string
    }
    
    // 接口实现类
    type Object struct {
    
    }
    
    // 实现方法即为实现接口
    func (object Object) toString() string {
    	return fmt.Sprintf("%s", &object)
    }
    
    // throws 方法
    func (object Object) throws(msg string) (string, error) {
    	return fmt.Sprintf("Error: %s", msg), object
    }
    
    // 实现error接口
    func (object Object) Error() string {
    	return fmt.Sprintf("Some errors occurred in %s and sub struct does not override this method!", object.toString())
    }
    
  18. 闭包 (闭包=函数+引用环境)

    func main() {
    	var txtSuffix = makeSuffix(".txt")
    	var name = txtSuffix("file")
    	fmt.Println(name) // file.txt
    }
    
    func makeSuffix(suffix string) func(name string) string {
    	return func(name string) string {
    		if !strings.HasSuffix(name, suffix) {
    			return name + suffix
    		}
    		return name
    	}
    }
    
  19. defer 返回时压栈处理

    // 1
    // Start
    // End
    // 阻塞...
    // (过了3s)
    // runtime: 1
    // 3
    // (过了3s)
    // runtime: 1
    // 2
    // (过了3s)
    // runtime: 1
    // 1
    func main() {
    	fmt.Println(runtime.NumGoroutine())
    	fmt.Println("Start")
    	defer runAndCheck(1)
    	defer runAndCheck(2)
    	defer runAndCheck(3)
    	fmt.Println("End")
    }
    
    func runAndCheck(value int) {
    	fmt.Printf("runtime: %d\n", runtime.NumGoroutine())
    	time.Sleep(time.Second * 3)
    	fmt.Println(value)
    }
    

    从以上示例可以看出

    1. defer 关键字修饰的同一作用域内函数在同一个 goroutine 内栈式执行 (先入后出)
    2. defer 修饰的函数在其父函数作用的 goroutine 内执行
  20. init()执行包级别的初始化,先于 mian(),自动被调用

  21. WaitGroup同步等待机制,相当于Java中的CountDownLatch

    func main() {
    	for i := 0; i < 10; i ++ {
    		go show(i)
    		waitGroup.Add(1) // 计数器 ++
    	}
    	waitGroup.Wait() // 阻塞等待
    	fmt.Println("End")
    }
    
    func show(i int) {
    	fmt.Println(i)
    	defer waitGroup.Done() // 计数器 --
    }
    
  22. 查询接口

    func main() {
    	one := Type1{}
    	two := Type2{}
    	// 解构,查询接口并转换
    	cast, ok := two.(Type1)
    	if ok {
    		fmt.Println(cast)
    	}
    }