参考网站

Go官方网址
Go官方中国镜像网址
Go中文爱好者网址

征服之路

1、Go开发环境搭建
2、HelloWorld
3、变量的声明
4、常量的声明
5、多返回值函数
6、包制作与导包
7、指针
8、defer
9、数组和切片
10、map
11、面向对象
12、反射
13、并发: goroutine & channel

Go开发环境搭建

官网参考

# download go-archive
$ wget https://golang.google.cn/dl/go1.17.7.linux-amd64.tar.gz

# Extract the archive you downloaded into /usr/local, creating a Go tree in /usr/local/go
$ sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.17.7.linux-amd64.tar.gz

# 配置GO相关环境变量
$ export GOROOT=/usr/local/go    # 编译器安装目录
$ export GOPATH=$HOME/go    # 放置Go代码的相关目录
$ export PATH=$PATH:$GOROOT/bin:$GOPATH/bin    # 把上面的路径添加到PATH环境变量

# 验证是否安装成功
$ go version
go version go1.17.7 linux/amd64

HelloWorld

$ mkdir -p $GOPATH/src/helloworld && cd $GOPATH/src/helloworld
$ vim helloworld.go
// helloworld
package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello World!")
}
$ go run helloworld.go
Hello World!

变量的声明

变量类型:
局部变量
全局变量

四种方式:
var a int
var b int = 1
var c = 1
d := 1 # 不支持全局变量

vi test.go
package main

import (
    "fmt"
)

var a int
var b int = 1
var c = 1

func main() {
    //只能在函数内定义, 在函数体外定义会报以下错误
    // syntax error: non-declaration statement outside function body
    d := 1    
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
    fmt.Println(d)
}
$ go run test.go
0
1
1
1
// 单行多变量声明
var b,c,d int = 1,1,1
var b,c,d = 1, true, "c"
// 多行多变量声明
var (
    b int = 1
    c bool
    d string = "c"
)

常量的声明

const (
    b int = 1
    c bool = true
    d string = "c"
)

func main(){
    //d = 2 常量不可以再赋值,会报以下错误
    //cannot assign to d (declared const)
}

// 关键字iota与常量的搭配使用
const (
    b int = iota + 2  // iota = 0
    c                 // iota = 1
    d                 // iota = 2
)
2
3
4

const (
    b, c int = iota + 2, iota + 3    // b, c = 0 + 2, 0 + 3
    d, e                           
    f, g                           
    h, i = iota * 2, iota * 3        // h, i = 3 * 2, 3 * 3
    j, k
    l, m
)
2 3
3 4
4 5
6 9
8 12
10 15

多返回值函数

package main

import (
    "fmt"
)

// 匿名写法
func f1() (int, int){
    return 1, 1
}

// 显名写法
func f2() (i int, j int){
    fmt.Println(i, j)
    i, j = 1, 1
    return i, j
}

// 半显半匿
func f3() (int, j int){
    fmt.Println(j)
    j = 1
    return 1, j
}

func main() {
    fmt.Println(f1())
    fmt.Println(f2())
    fmt.Println(f3())
}
$ go run test.go            
1 1
0 0
1 1
0
1 1

包制作与导包

# 包制作
$ go env -w GO111MODULE=off
$ tree $GOPATH/src/pkg                                        
$HOME/go/src/pkg
├── lib_1
│   └── main.go
└── lib_2
    └── main.go
// ../lib_1/main.go
import (
    "fmt"
)

func Test(){
    fmt.Println("This is a Test function of lib_1...")
}

func init(){
    fmt.Println("This is a init function of lib_1...")
}

// ../lib_2/main.go
package lib_2

import (
    "fmt"
)

func Test(){
    fmt.Println("This is a Test function of lib_2...")
}

func init(){
    fmt.Println("This is a init function of lib_2...")
}
# 导包
$ vi test.go
package main

import (
    //别名导包
    mylib1 "pkg/lib_1"
    mylib2 "pkg/lib_2"
)

func main() {
    
    mylib1.Test()
    mylib2.Test()
}
$ go run test.go                         
This is a init function of lib_1...
This is a init function of lib_2...
This is a Test function of lib_1...
This is a Test function of lib_2...
package main

import (
    // 匿名导包, 无法使用当前包的方法, 但是会执行当前包内部的init方法
    _ "pkg/lib_1"
    mylib2 "pkg/lib_2"
)

func main() {
    //mylib1.Test()
    mylib2.Test()
}
$ go run test.go       
This is a init function of lib_1...
This is a init function of lib_2...
This is a Test function of lib_2...

指针

package main

import (
    "fmt"
)

func Vchange(i int){
    i = 1
}

func Pchange(i *int){
    *i = 1
}

func main() {
    var a int
    fmt.Println(a)
    Vchange(a)
    fmt.Println(a)
    Pchange(&a)
    fmt.Println(a)
}
$ go run test.go               
0
0
1

defer

# 多函数弹栈式执行
$ vi deferFuns.go
// deferFuns.go
package main

import (
    "fmt"
)

func fun1() {
    fmt.Println("This is function 1...")
}

func fun2() {
    fmt.Println("This is function 2...")
}

func fun3() {
    fmt.Println("This is function 3...")
}

func main(){
    defer fun1()
    defer fun2()
    defer fun3()
}
$ go run deferFuns.go                   
This is function 3...
This is function 2...
This is function 1...
# return、defer顺序执行
$ vi returnAndDefer.go
package main

import (
    "fmt"
)

func retFuns() int{
    fmt.Println("This is a return function...")
    return 0
}

func deferFuns(){
    fmt.Println("This is a defer function...")
}

func retAdef() int {
    defer deferFuns()
    return retFuns()
}

func main() {
    retAdef()
}
$ go run returnAndDefer.go        
This is a return function...
This is a defer function...

数组和切片

本人此前做过汇总介绍,此处不再赘叙,感兴趣跳转此页面了解详情

map

声明
package main

import(
    "fmt"
)

func main() {
    //第一种
    var map1 map[int]string
    fmt.Println(map1)
    
    //使用前需用make分配数据空间
    map1 = make(map[int]string)
    map1[1] = "1"
    fmt.Println(map1)

    //第二种
    map2 := make(map[int]string)
    fmt.Println(map2)
    map2[1] = "1"
    fmt.Println(map2)

    //第三种
    map3 := map[int]string{1:"1"}
    fmt.Println(map3)
}
$ go run src/test/map.go        
map[]
map[1:1]
map[]
map[1:1]
map[1:1]
操作
package main

import(
    "fmt"
)

func PrintMap(m map[int]string){
    for k,v := range m {
        fmt.Printf("%v: %v\n",k,v)
    }
}

func main() {
    map1 := map[int]string{
        1:"one",
        2:"two",
        3:"three",
    }
    fmt.Println(map1)
    
    //增加
    map1[4] = "four"
    fmt.Println(map1)

    //修改
    map1[2] = "2"
    fmt.Println(map1)

    //删除
    delete(map1, 1)
    fmt.Println(map1)

    //遍历
    PrintMap(map1)
}
$ go run src/test/map.go         
map[1:one 2:two 3:three]
map[1:one 2:two 3:three 4:four]
map[1:one 2:2 3:three 4:four]
map[2:2 3:three 4:four]
2: 2
3: three
4: four

面向对象

封装
继承
多态
封装
切入点:
结构体
指针
函数

定义:
将某一类事物抽象成一个(属性、方法)的集合,该集合是一个模板,用于生成具有实际意义的对象
属性的集合-结构体
方法-指向结构体的指针的函数
package main

import (
    "fmt"
)

//类,对象模板,属性和方法的集合
//定义属性
type Human struct {
    sex string
    age int
    name string
}

// 定义方法
// 操作结构体的拷贝,假的类方法定义
func (this Human) setAge(a int){
    this.age = a
}

// 操作结构体的引用,真的类方法定义
func (this *Human) setName(n string) {
    this.name = n
}

func main() {
    h1 := &Human{
        sex: "man",
        age: 18,
        name: "lilei",
    }

    h2 := Human{
        sex: "man",
        age: 18,
        name: "lilei",
    }

    //真假方法比较
    fmt.Printf("Before: %v\n", h2.age)
    h2.setAge(20)
    fmt.Printf("After: %v\n", h2.age)

    fmt.Printf("Before: %v\n", h1.name)
    h1.setName("liming")
    fmt.Printf("After: %v\n", h1.name)
}
$ go run Human.go         
Before: 18
After: 18
Before: lilei
After: liming
继承
切入点:
子类继承父类的属性和方法
子类重写父类的方法
package main

import (
    "fmt"
)

// 定义父类的属性和方法
type Human struct {
    sex string
    age int
    name string
}

// 父类的方法
func (this *Human) Talk() {
    fmt.Println("human can talk")
}

func (this *Human) Walk() {
    fmt.Println("human can walk")
}

func (this *Human) Eat() {
    fmt.Println("human can eat")
}

// 定义子类
type Spiderman struct{
    Human  // 继承父类
    superpower string
}

// 重写父类的Walk方法
func (this *Spiderman) Walk(){
    fmt.Println("Spiderman not only can walk, but also can climb to the top of building")
}

func main() {
    // s := Spiderman{Human{"man",18,"peter"}, "spider-like power"}
    var s Spiderman
    s.sex = "man"
    s.age = 18
    s.name =  "peter"
    s.superpower = "spider-like power"
    
    fmt.Println(s.superpower)
    s.Talk()
    s.Walk()
}
$ go run Spiderman.go           
spider-like power
human can talk
Spiderman not only can walk, but also can climb to the top of building
多态
切入点:
接口 - 类的方法的模板,本质是一个指针
类中会具体地实现接口中的方法
package main

import(
    "fmt"
)

// 接口Superman
type Superman interface {
    fly()
    run()
    fight()
}

// 具体的类 Batman
type Batman struct {
    ability string
}

func (this *Batman) fly(){
    fmt.Printf("fly like a %v\n", this.ability)
}

func (this *Batman) run(){
    fmt.Printf("run like a %v\n", this.ability)
}

func (this *Batman) fight(){
    fmt.Printf("fight like a %v\n", this.ability)
}

// 具体的类 Spiderman
type Spiderman struct {
    ability string
}

func (this *Spiderman) fly(){
    fmt.Printf("fly like a %v\n", this.ability)
}

func (this *Spiderman) run(){
    fmt.Printf("run like a %v\n", this.ability)
}

func (this *Spiderman) fight(){
    fmt.Printf("fight like a %v\n", this.ability)
}

// 多态的例子
func InfoAbility(s Superman){
    s.fly()
    s.run()
    s.fight()
}

func main(){
    // var s Superman
    // s = &Batman{"bat"}
    // s.fly()
    // s.run()
    // s.fight()

    // s = &Spiderman{"spider"}
    // s.fly()
    // s.run()
    // s.fight()

    InfoAbility(&Batman{"bat"})
    InfoAbility(&Spiderman{"spider"})
}
$ go run interface.go
fly like a bat
run like a bat
fight like a bat
fly like a spider
run like a spider
fight like a spider
interface{}是万能的数据类型
package main

import(
    "fmt"
)

func showArg(arg interface{}){
    fmt.Println(arg)
}

type example struct{
    exp string
}

func main(){
    e := example{"for example"}
    showArg(e)
    showArg("Hello world")
    showArg(18)
}
$ go run interface.go       
{for example}
Hello world
18

反射

interface{}是万能的数据类型
package main

import(
    "fmt"
)

func main(){
    var a string
    a = "bcd"

    var b interface{}
    b = a

    var c int
    c = 1

    str, err := b.(string)
    

    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(str, err)

    b = c
    i, err := b.(int)
    fmt.Println(c)
    fmt.Println(b)
    fmt.Println(i, err)
}
$ go run test.go                                        
bcd
bcd
bcd true
1
1
1 true
reflect包常用的两个函数
TypeOf
ValueOf
package main

import(
    "fmt"
    "reflect"
)

func reflectAnt(arg interface{}){
    fmt.Println("type: ", reflect.TypeOf(arg))
    fmt.Println("value: ", reflect.ValueOf(arg))
}

func main(){
    a := 1
    b := "abc"
    c := 3.14

    reflectAnt(a)
    reflectAnt(b)
    reflectAnt(c)
}
$ go run test.go         
type:  int
value:  1
type:  string
value:  abc
type:  float64
value:  3.14
package main

import (
    "fmt"
    "reflect"
)

type User struct {
    Id   int
    Name string
    Age  int
}

func (this User) Call() {
    fmt.Println("user is called ..")
    fmt.Printf("%v\n", this)
}

func main() {
    user := User{1, "Aceld", 18}

    DoFiledAndMethod(user)
}

func DoFiledAndMethod(input interface{}) {
    //获取input的type
    inputType := reflect.TypeOf(input)
    fmt.Println("inputType is :", inputType.Name())

    //获取input的value
    inputValue := reflect.ValueOf(input)
    fmt.Println("inputValue is:", inputValue)

    //通过type 获取里面的字段
    //1. 获取interface的reflect.Type,通过Type得到NumField ,进行遍历
    //2. 得到每个field,数据类型
    //3. 通过filed有一个Interface()方法等到 对应的value
    for i := 0; i < inputType.NumField(); i++ {
        field := inputType.Field(i)
        value := inputValue.Field(i).Interface()

        fmt.Printf("%s: %v = %v\n", field.Name, field.Type, value)
    }

    //通过type 获取里面的方法,调用
    for i := 0; i < inputType.NumMethod(); i++ {
        m := inputType.Method(i)
        fmt.Printf("%s: %v\n", m.Name, m.Type)
    }
}
$ go run test.go
inputType is : User
inputValue is: {1 Aceld 18}
Id: int = 1
Name: string = Aceld
Age: int = 18
Call: func(main.User)
package main

import (
    "fmt"
    "reflect"
)

type resume struct {
    Name string `info:"name" doc:"我的名字"`
    Sex  string `info:"sex"`
}

func findTag(str interface{}) {
    t := reflect.TypeOf(str).Elem()

    for i := 0; i < t.NumField(); i++ {
        taginfo := t.Field(i).Tag.Get("info")
        tagdoc := t.Field(i).Tag.Get("doc")
        fmt.Println("info: ", taginfo, " doc: ", tagdoc)
    }
}

func main() {
    var re resume

    findTag(&re)

}
$ go run test.go                 
info:  name  doc:  我的名字
info:  sex  doc:

并发: goroutine & channel

切入点:
进程、线程
goroutine
channel
进程、线程

进程看作资源空间,存放程序运行时需要的一切资源(如上图所示包括但不限的内存地址空间、文件和设备的句柄、线程)

线程看作执行空间,执行加载到内存中的主函数或是程序的某一段代码
goroutine

...


BewaterMyfriends
19 声望1 粉丝

IT从业者 数字游民 创业者