回首页

[TOC]

go入门教程学习记录

一 安装

1下载

https://golang.org/dl/

2解压

tar -C /usr/local -xzf xxx.tar.gz

3环境变量

echo 'export GOPATH=$HOME/Code/go' >> $HOME/.profile
echo 'export PATH=$PATH:/usr/local/go/bin' >> $HOME/.profile
source $HOME/.profile

4成功验证

go version
go version go1.12.5 linux/amd64

二 运行 hello world

package main

func main() {

  println("Hello World \n")
}

三 变量声明

四 结构体

类似 class

1 声明结构体

类似于创建一个 class

type Saiyan struct {
  Name string
  Power int
}

2 初始化

类似于实例化class

goku := Saiyan{
  Name: "Goku",
  Power: 9000,
}
goku := Saiyan{}
goku := Saiyan{Name: "Goku"}
goku.Power = 9000
goku := Saiyan{"Goku", 9000}

3 结构体的引用传值

php 类的都是引用传值的,go需要指定

非引用,输出9000

func main() {
  goku := Saiyan{"Goku", 9000}
  Super(goku)
  fmt.Println(goku.Power) //输出9000
}

func Super(s Saiyan) {
  s.Power += 10000
}

引用传值输出 19000

func main() {
  goku := &Saiyan{"Goku", 9000}
  Super(goku)
  fmt.Println(goku.Power)
}

func Super(s *Saiyan) {
  s.Power += 10000
}

4 给结构体添加方法

类似于给类,添加一个函数

type Saiyan struct {
  Name string
  Power int
}

func (s *Saiyan) Super() {
  s.Power += 10000
}

调用,输出19001

goku := &Saiyan{"Goku", 9001}
goku.Super()
fmt.Println(goku.Power) // 将会打印出 19001

5 工厂函数

func NewSaiyan(name string, power int) *Saiyan {
  return &Saiyan{
    Name: name,
    Power: power,
  }
}

等效于

func NewSaiyan(name string, power int) Saiyan {
  return Saiyan{
    Name: name,
    Power: power,
  }
}

6 给结构体添加结构体字段

类似于类的组合

声明

type Saiyan struct {
  Name string
  Power int
  Father *Saiyan
}

初始化

gohan := &Saiyan{
  Name: "Gohan",
  Power: 1000,
  Father: &Saiyan {
    Name: "Goku",
    Power: 9001,
    Father: nil,
  },
}

7 使用组合结构体的方法

Person结构体,有一个方法Introduce

type Person struct {
  Name string
}

func (p *Person) Introduce() {
  fmt.Printf("Hi, I'm %s\n", p.Name)
}

Saiyan结构体的字段是 Person

type Saiyan struct {
  *Person
  Power int
}

初始化

goku := &Saiyan{
  Person: &Person{"Goku"},
  Power: 9001,
}

调用 person 的 'Introduce' 方法,隐式调用

goku.Introduce()

或者

goku.Person.Introduce()

fmt.Println(goku.Name)
fmt.Println(goku.Person.Name)

五 数组

go 的数组,是固定长度的

声明

方式1

var scores [10]int
scores[0] = 339

方式2

scores := [4]int{9001, 9333, 212, 33}

循环数组

for index, value := range scores {

}

六 切片【索引数组】

动态数组 len(arr) 数组长度 ,索引数组

声明

names := []string{"leto", "jessica", "paul"}
checks := make([]bool, 10) //长度是 10 ,容量是 10 
var names []string
scores := make([]int, 0, 10) //长度是 0 ,容量是 10

scores := make([]int, 0, 10) 长度为0 ,时不能通过scores[key]=value的形式赋值 ,可以这样:

scores := make([]int, 0, 10)
scores = scores[0:8]
scores[7] = 9033
fmt.Println(scores)

checks := make([]bool, 10) 例子:

func extractPowers(saiyans []*Saiyans) []int {
  powers := make([]int, len(saiyans))
  for index, saiyan := range saiyans {
    powers[index] = saiyan.Power
  }
  return powers
}

var names []string,长度未知,例子:

names =  append(names, "小明")

切割,会改变原切片

scores := []int{1,2,3,4,5}
slice := scores[2:4]
slice[0] = 999
fmt.Println(scores) //输出是 [1, 2, 999, 4, 5]。

移除元素

func main() {
  scores := []int{1, 2, 3, 4, 5}
  scores = removeAtIndex(scores, 2)
  fmt.Println(scores) // [1 2 5 4]
}

// 不会保持顺序
func removeAtIndex(source []int, index int) []int {
  lastIndex := len(source) - 1
  // 交换最后一个值和想去移除的值
  source[index], source[lastIndex] = source[lastIndex], source[index]
  return source[:lastIndex]
}

复制切片

import (
  "fmt"
  "math/rand"
  "sort"
)

func main() {
  scores := make([]int, 100)
  for i := 0; i < 100; i++ {
    scores[i] = int(rand.Int31n(1000))
  }
  sort.Ints(scores)

  worst := make([]int, 5)
  copy(worst, scores[:5]) //大于worst的长度,[0 2 2 15 26],小于worst的长度 [0 2 2 15 0]
  fmt.Println(worst)
   fmt.Println(scores)
}

七 映射【关联数组】

声明

  lookup := make(map[string]int)
  lookup := make(map[string]int, 100)
  lookup := map[string]int{
  "goku": 9001,
  "gohan": 2044,
}

例子:

func main() {
  lookup := make(map[string]int)
  lookup["goku"] = 9001
  power, exists := lookup["vegeta"] //判断key

  // prints 0, false
  // 0 is the default value for an integer
  fmt.Println(power, exists)
}

删除索引

delete(lookup, "goku")

作为结构体的属性时:

type Saiyan struct {
  Name string
  Friends map[string]*Saiyan
}
goku := &Saiyan{
  Name: "Goku",
  Friends: make(map[string]*Saiyan),
}
goku.Friends["krillin"] = ... //加载或者创建 Krillin

迭代

for key, value := range lookup {

}

八 代码组织

避免循环导入,即两个包互相引入,解决方法是,提取公共部分到一个包中。类似于jsutils

1 目录结构

src 在环境变量 GOPATH下,shopping 表示一个模块,其目录下的文件。会自动导入,其他文件夹下的文件。可以按需手动导入。

 src
    └── shopping
        ├── db
        │   └── db.go
        ├── main
        │   └── main.go
        └── pricecheck.go

2 接口

定义

type Logger interface {
  Log(message string)
}

实现接口

type ConsoleLogger struct {}
func (l ConsoleLogger) Log(message string) {
  fmt.Println(message)
}

定义带有接口的结构体

type Server struct {
  logger Logger
}

初始化

server := &Server{
    logger: &ConsoleLogger{}
}
server.logger.Log("log info")

完整例子:

package main
import (
  "fmt"
)

type Logger interface {
  Log(message string)
}
type ConsoleLogger struct {}
func (l ConsoleLogger) Log(message string) {
         fmt.Println(message)
}
type Server struct {
  logger Logger
}
func main() {
        server := &Server{
                logger: &ConsoleLogger{},
        }
        server.logger.Log("log info")
}