七叶笔记 » golang编程 » golang关键字学习

golang关键字学习

1. var, const

定义变量和常量

 var name string
var name string = "myName" //string 能够被自动推断, 可以省略
var name1, name2, name3 string = "name1", "name2", "name3" //string 能够被自动推断, 可以省略
var (
  name = "myName"
  age = 18
)

// := 简短声明, 只能用在函数内部
name1, name2, name3 := "name1", "name2", "name3"
  

2. package, import

定义包和引入包

包名按约定应使用小写字符

包中的函数或变量等, 首字母为大写时, 将被导入, 可使用; 首字母的大小写, 类似于 java 中的 public private

 package main

import "find-in-file/cmd"

// 多个包引入
import (
  "bufio"
  "fmt"
  "log"
  "os"
  "strings"
)

// 别名
import (
  "os"

  myHomeDir "github.com/mitchellh/go-homedir"
  "github.com/spf13/viper"
)  

3. map

内置数据类型

4. func

定义函数

5. return, defer

函数的返回和延迟执行

defer 经常用于资源的释放, 会在 return 之前执行; 多个 defer 语句, 越后面的越先执行, 后入先出 ;

相比 java 中的 try-with-resources 更优雅

 func test() {   
  f, err := os.Open(filename)   
  if err != nil {
    panic(err)
  }   
  defer f.Close()
  // 针对文件f 的具体操作...
}
  
 package main

import "fmt"

func main() {
  a := test()
  fmt.Println("a is", a, "after return")
}

func test() (r int) {
  a := 0
  fmt.Println("p1 a is", a)
  defer func(a int) (r int){
    fmt.Println("a is", a, "in defer")
    return a + 1
  }(a)

  a = a +1
  fmt.Println("p2 a is", a)
  return a
}
//以下为执行结果
//p1 a is 0
//p2 a is 1
//a is 0 in defer
//a is 1 after return
  

6. type,struct

type 关键字用于定义类型

struct 表示为结构体类型, 是值类型, 赋值和传参会拷贝内容(区别于 java 语言)

 type Person struct {
  Name string
  Age int
}

func main() {
  p := Person{ 
    Name: "张三", 
    Age:  20, 
  } 
  p.Age = 25 
  fmt.Println(p)
}

//匿名类型
type Person struct { 
  Name string 
  Attr struct{
    age int
  }
}

//嵌入组合
package main

import "fmt"

type Person struct {
  Name string
  Age  int
}

type Worker struct {
  Person
  Name string
}

func main() {
  p := Person{
    Name: "张三",
    Age:  18,
  }

  fmt.Printf("%v\n", p)
  p.Age = 25
  fmt.Printf("%v\n", p)

  w := Worker{
    Person: Person{
      Name: "张三",
      Age:  25,
    },
    Name: "建筑工人",
  }
  fmt.Printf("%v\n", w)
  //当被嵌入结构中的某个字段与当前struct中已存在的字段同名时,
  //编译器从外向内逐级查找所有层次的匿名字段,
  //直到发现目标或者报错
  fmt.Printf("%s\n", w.Name)
  fmt.Printf("%s\n", w.Person.Name)
  fmt.Printf("%d\n", w.Age)
}

//输出打印
//{张三 18}
//{张三 25}
//{{张三 25} 建筑工人}
//建筑工人
//张三
//25

  

7. interface

接口类型

 //期中空接口, 非常常用, 即不需要实现任何方法, 
//可以看fmt#Print 相关方法

package main

import "fmt"

type SaySomeThing interface {
  Say()
}

type Human struct {
  Name string
}

type Dog struct {
  Name string
}

func (p *Human) Say() {
  fmt.Println("哈哈哈")
}

func (d *Dog) Say() {
  fmt.Println("汪汪汪")
}

func main() {
  h := Human{
    Name: "张三",
  }
  test(&h)
  d := Dog{
    Name: "二哈",
  }
  test(&d)
}

func test(canSay SaySomeThing) {
  canSay.Say()
  fmt.Println("使用接口成功调用")
}
  

9. for, break, continue, goto, range

循环控制语句

 i := 1 
for i <= 3 {
  fmt.Println(i)
  i = i + 1 
}

for j := 7; j <= 9; j++ {
  fmt.Println(j)
}

for {
  fmt.Println("loop")
  break
}  

10. if, else

 if num := 9; num < 0 {
  fmt.Println(num, "is negative") 
} else if num < 10 {
  fmt.Println(num, "has 1 digit")
} else {
  fmt.Println(num, "has multiple digits")
}
  

11. switch, case, default, fallthrough

区别于 java , 每个 case 都可以理解为自动带了 break ;

如果想继续执行后面分支的代码, 则需 fallthrough ;

 switch sExpr {   
  case expr1:
    doSomeThing1()
  case expr2:       
    doSomeThing2()
  case expr3:
    doSomeThing3()
  default:       
    doDefault()
}
  

12. go

开启协程异步执行

 package main

import (
  "fmt"
  "sync"
)

func main() {
  wg := sync.WaitGroup{}
  //异步干3件事
  wg.Add(3)
  go func() {
    r := add(1, 2)
    fmt.Println("r is", r)
    wg.Done()
  }()

  go func() {
    r := add(2, 3)
    fmt.Println("r is", r)
    wg.Done()
  }()

  go func() {
    r := add(3, 4)
    fmt.Println("r is", r)
    wg.Done()
  }()

  fmt.Println("开始等待...")
  wg.Wait()
  fmt.Println("都完成了...")
}

func add(a int, b int) (c int) {
  return a + b
}


//开始等待...
//r is 3
//r is 5
//r is 7
//都完成了...

//这个例子太简单, 都说并发编程是go 最牛叉的特性, 这里还不能充分体现出来;
//结合channel 等编程, 才是实战中最常用的情况;  

13. select

一个select语句用来选择哪个case中的发送或接收操作可以被立即执行。它类似于switch语句,但是它的case涉及到channel有关的I/O操作

 package main

import (
  "fmt"
  "time"
)

func main() {
  // 本例中,我们从两个通道中选择
  c1 := make(chan string)
  c2 := make(chan string)
  // 为了模拟并行协程的阻塞操作,我们让每个通道在一段时间后再写入一个值
  go func() {
    //每1秒发送
    for {
      time.Sleep(time.Second * 1)
      c1 <- "one"
    }
  }()
  go func() {
    //每2秒发送
    for {
      time.Sleep(time.Second * 2)
      c2 <- "two"
    }
  }()
  // 我们使用select来等待这两个通道的值,然后输出
  for i := 0; i < 10; i++ {
    select {
    case msg1 := <-c1:
      fmt.Println("received from c1", msg1)
    case msg2 := <-c2:
      fmt.Println("received from c2", msg2)
    }
  }
}

  

14. chan

channel 通道, 可以理解为一个简单的消息队列;

一般结合内置函数 make 使用;

 c1 := make(chan string)
c2 := make(chan string, 10)  

相关文章