go快速入门

环境搭建

  • 下载go(https://studygolang.com/dl),配置环境变量,cmd输go验证
    go快速入门_第1张图片

  • 下载vscode(https://code.visualstudio.com/),并移至/Applications

介绍

优势

  • 编译成机器码,不依赖其他库,直接运行即部署
  • 静态类型语言,编译期检查出隐藏的大多数问题
  • 语言层面并发,充分利用多核
  • 强大的标准库,runtime系统调度机制,高效GC,丰富的标准库
  • 简单,25个关键字,C语言简洁基因,面向对象,跨OS平台
  • 性能,编译运行速度堪比C语言

不足

  • 包管理,大部分在GitHub上
  • 无泛型
  • 无Exception,都是Error
  • 不能完全兼容C,C是可以直接写ASM且完全兼容

Hello Go

hello.go

package main

import "fmt"

func main() {
	fmt.Println("Hello, Go!")
}

go快速入门_第2张图片

VSCode方式

// go.mod文件不存在问题解决
go env -w GO111MODULE=on
go mod init hello

// 下载包超时问题,安装方式Help -> Show All Commands -> Go:Install/Update
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

语法

init方法

lib.go

package lib

import "fmt"

// 小写开头,包内可访问,外包不可访问
func init() {
	fmt.Println("init...")
}

// 大写开头,包内外都可访问
func Test() {
	fmt.Println("test...")
}

go快速入门_第3张图片

指针

package main

import "fmt"

func swap(a *int, b *int) {
	var t int = *a
	*a = *b
	*b = t
}

func main() {
	var a, b int = 1, 2
	swap(&a, &b)
	fmt.Printf("a = %d, b = %d\n", a, b)
}

defer

defer函数在return之后调用,多个defer执行顺序是弹栈顺序

数组与切片

长度固定

package main

import "fmt"

// 值传递
func printArr(arr [3]int) {
	for i, v := range arr {
		fmt.Printf("arr[%d]=%d\n", i, v)
	}
	arr[0] = 100
}

func main() {
	var arr1 [2]int
	arr2 := [3]int{1}

	fmt.Printf("arr1 type=%T\n", arr1)
	for i := 0; i < len(arr1); i++ {
		fmt.Printf("arr1[%d]=%d\n", i, arr1[i])
	}

	fmt.Println("============================")

	fmt.Printf("arr2 type=%T\n", arr2)
	for i, v := range arr2 {
		fmt.Printf("arr2[%d]=%d\n", i, v)
	}

	fmt.Println("============================")

	printArr(arr2)

	fmt.Println("============================")

	for i, v := range arr2 {
		fmt.Printf("arr2[%d]=%d\n", i, v)
	}

}

go快速入门_第4张图片
长度不定(切片)

package main

import "fmt"

// 引用传递
func printArr(arr []int) {
	for i, v := range arr {
		fmt.Printf("arr[%d]=%d\n", i, v)
	}
	arr[0] = 100
}

func main() {
	arr := []int{1, 2, 3}
	fmt.Printf("arr type=%T\n", arr)
	printArr(arr)

	fmt.Println("============================")

	for i, v := range arr {
		fmt.Printf("arr[%d]=%d\n", i, v)
	}

}

go快速入门_第5张图片

package main

import "fmt"

func main() {
	var slice []int
	fmt.Printf("len = %d, slice = %v\n", len(slice), slice)
	if slice == nil {
		fmt.Println("slice is nil")
	}
	// slice[0] = 1 // 越界
	slice = make([]int, 3)
	fmt.Printf("len = %d, slice = %v\n", len(slice), slice)
}

go快速入门_第6张图片

package main

import "fmt"

func main() {
	var slice = make([]int, 3, 5)
	fmt.Printf("len = %d, capacity = %d, slice = %v\n", len(slice), cap(slice), slice)

	slice = append(slice, 4)
	fmt.Printf("len = %d, capacity = %d, slice = %v\n", len(slice), cap(slice), slice)

	slice = append(slice, 5)
	fmt.Printf("len = %d, capacity = %d, slice = %v\n", len(slice), cap(slice), slice)

	// 会扩容一倍
	slice = append(slice, 6)
	fmt.Printf("len = %d, capacity = %d, slice = %v\n", len(slice), cap(slice), slice)

	// slice2和slice指针地址相同,修改slice2[0]等同于修改了slice[0]
	slice2 := slice[:4]
	slice2[0] = 100
	fmt.Println(slice)

	// copy
	slice3 := make([]int, 3)
	copy(slice3, slice)
	fmt.Println(slice3)

}


go快速入门_第7张图片

map


package main

import (
	"fmt"
)

// 引用传递
func printMap(m map[int]string) {
	for k, v := range m {
		fmt.Printf("%d -> %s\n", k, v)
	}
}

func main() {
	fmt.Println("-------------m-------------")
	var m = map[int]string{}
	fmt.Printf("len = %d, m = %v, type = %T\n", len(m), m, m)
	m[1] = "a"
	m[2] = "b"
	fmt.Printf("len = %d, m = %v, type = %T\n", len(m), m, m)

	fmt.Println("-------------m2-------------")
	m2 := map[int]string{
		1: "aa",
		2: "bb",
		3: "cc",
	}
	printMap(m2)

	fmt.Println("-------------m3-------------")
	m3 := make(map[int]string, 6)
	m3[1] = "aaa"
	m3[2] = "bbb"
	printMap(m3)

	fmt.Println("-------------m3-------------")
	delete(m3, 1)
	printMap(m3)

}

go快速入门_第8张图片

struct

package main

import (
	"fmt"
)

type Student struct {
	id    int
	name  string
	score int
}

// 引用传递
func addScore(stu *Student, add int) {
	stu.score += add
}

// 值传递
func addScore0(stu Student, add int) {
	stu.score += add
}

func main() {
	fmt.Println("---------stu---------")
	var stu = &Student{
		id:    1,
		name:  "Tom",
		score: 90,
	}
	fmt.Printf("stu = %v\n", stu)
	addScore(stu, 5)
	fmt.Printf("stu = %v\n", stu)

	fmt.Println("---------stu2---------")
	var stu2 Student
	stu2.id = 2
	stu2.name = "Jack"
	stu2.score = 92
	fmt.Printf("stu2 = %v\n", stu2)
	addScore0(stu2, 5) // 值传递
	// addScore(&stu2, 5) // 引用传递

	fmt.Printf("stu2 = %v\n", stu2)
}

go快速入门_第9张图片

面向对象

封装

package main

import (
	"fmt"
)

type Account struct {
	id   int
	name string
}

func (ac *Account) Show() {
	fmt.Printf("[Account]{id:%d, name=%s}\n", ac.id, ac.name)
}

// 引用传递
func (ac *Account) SetName(name string) {
	ac.name = name
}

func main() {
	fmt.Println("---------Account---------")
	ac := Account{id: 999, name: "Ahha"}
	ac.Show()
	ac.SetName("ahhA")
	ac.Show()
}

go快速入门_第10张图片

继承

package main

import (
	"fmt"
)

type Person struct {
	id   int
	name string
}

type Student struct {
	Person
	score int
}

func (person *Person) Eat() {
	fmt.Printf("Person.Eat\n")
}

func (stu *Student) Eat() {
	fmt.Printf("Student.Eat\n")
}

func (stu *Student) Score() {
	fmt.Printf("Student.Score\n")
}

func main() {
	stu := Student{
		Person: Person{id: 999, name: "abc"},
		score:  90,
	}
	stu.Eat()
	stu.Person.Eat()
	stu.Score()
}

多态

package main

import (
	"fmt"
)

// 本身已是指针
type Animal interface {
	Sleep()
	GetKind() string
}

type Cat struct {
	kind string
}

func (cat *Cat) Sleep() {
	fmt.Println("Cat is sleeping.")
}

func (cat *Cat) GetKind() string {
	return "cat"
}

type Dog struct {
	kind string
}

func (cat *Dog) Sleep() {
	fmt.Println("Dog is sleeping.")
}

func (cat *Dog) GetKind() string {
	return "dog"
}

func show(animal Animal) {
	fmt.Printf("kind = %s\n", animal.GetKind())
	animal.Sleep()
	fmt.Println()
}

func main() {
	var animal1 Animal = &Cat{kind: "cat"}
	var animal2 Animal = &Dog{kind: "dog"}

	show(animal1)
	show(animal2)
}

interface{}

package main

import (
	"fmt"
)

// interface{}是万能类型
func IsString(arg interface{}) {
	fmt.Println("arg = ", arg)
	value, ok := arg.(string)	// 断言
	if ok {
		fmt.Println("arg is string type, value =", value)
	} else {
		fmt.Printf("arg is not string type, type = %T\n", arg)
	}
	fmt.Println()
}

func main() {
	IsString(123)
	IsString("xxx")

}

go快速入门_第11张图片
pair

package main

import "fmt"

func main() {
	// 任何变量都内置pair,赋给interface{}时,类型是确定的静态类型或具体类型
	s := "123"
	var anyType interface{} = s
	if _, ok := anyType.(string); ok {
		fmt.Println("s =", s)
	}
}

反射

struct反射

package main

import (
	"fmt"
	"reflect"
)

type User struct {
	Id   int    `info:"id" doc:"unique id"`
	Name string `info:"name" doc:"user name"`
	Age  int    `info:"age"`
}

func (user User) Call() int {
	fmt.Printf("user = %v", user)
	return user.Id
}

func main() {
	user := User{Id: 1, Name: "Tom", Age: 20}

	Reflect(user)
	ReflectTags(&user)
}

func Reflect(input interface{}) {
	inputType := reflect.TypeOf(input)
	fmt.Println("input type =", inputType.Name())

	inputValue := reflect.ValueOf(input)
	fmt.Println("input value =", inputValue)

	for i := 0; i < inputType.NumField(); i++ {
		field := inputType.Field(i)
		value := inputValue.Field(i).Interface()
		fmt.Printf("%s: %s = %v\n", field.Name, field.Type, value)
	}

	for i := 0; i < inputType.NumMethod(); i++ {
		method := inputType.Method(i)
		fmt.Printf("%s: %v\n", method.Name, method.Type)
	}

}

func ReflectTags(input interface{}) {
	tags := reflect.TypeOf(input).Elem()
	for i := 0; i < tags.NumField(); i++ {
		tagInfo := tags.Field(i).Tag.Get("info")
		tagDoc := tags.Field(i).Tag.Get("doc")
		fmt.Println("tag info =", tagInfo, ", doc =", tagDoc)
	}
}

go快速入门_第12张图片
struct标签在json中的应用

package main

import (
	"encoding/json"
	"fmt"
)

type User struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func main() {
	var err error

	user := User{Id: 1, Name: "Tom", Age: 20}

	// struct转json
	jstr, err := json.Marshal(user)
	if err != nil {
		fmt.Println("json marshal error,", err)
	} else {
		// jstr = {"id":1,"name":"Tom","age":20}
		fmt.Printf("jstr = %s\n", jstr)
	}

	user2 := User{}
	// json转struct
	err = json.Unmarshal(jstr, &user2)
	if err != nil {
		fmt.Println("json unmarshal error,", err)
	} else {
		// user = {1 Tom 20}
		fmt.Println("user =", user2)

	}
}

go routine

package main

import (
	"fmt"
	"time"
)

func main() {
	go func() {
		defer fmt.Println("A.defer")

		func() {
			defer fmt.Println("B.defer")
			// runtime.Goexit() // 退出协程
			fmt.Println("B")
		}()

		fmt.Println("A")
	}()

	for {
		fmt.Println("main")
		time.Sleep(3 * time.Second)
	}
}

channel

协程通信

  • 无缓冲,存等待对方取,取等待对方存
  • 有缓冲,缓冲队列满了存才被阻塞,缓冲队列空了取才被阻塞
// 无缓冲
package main

import (
	"fmt"
)

func main() {
	c := make(chan int)

	go func() {
		c <- 999
	}()

	num := <-c	// <-c 无空格

	fmt.Println("num =", num)
}

// 有缓冲
package main

import (
	"fmt"
	"time"
)

func main() {
	c := make(chan int, 3)

	go func() {
		defer fmt.Println("sub end")

		for i := 0; i < 4; i++ {
			c <- i
			fmt.Println("sub running, i =", i, ", len =", len(c), ", capacity =", cap(c))
		}
	}()

	time.Sleep(time.Second * 1)

	for i := 0; i < 4; i++ {
		num := <-c
		fmt.Println("num =", num)
		time.Sleep(time.Second * 1)
	}

	fmt.Println("main end")
}

go快速入门_第13张图片
关闭channel

package main

import (
	"fmt"
)

func main() {
	c := make(chan int)

	go func() {
		for i := 0; i < 3; i++ {
			c <- i
		}
		close(c) // 若不关闭,会报死锁。fatal error: all goroutines are asleep - deadlock!
	}()

	// for data := range c {
	// 	fmt.Println(data)
	// }
	
	for {
		if data, ok := <-c; ok {
			fmt.Println(data)
		} else {
			break
		}
	}

	fmt.Println("main end")
}

go module

go path 不能进行版本控制,不能指定引入的第三方库的版本,所以引入了 go mod。引入第三方包后出现 go.sum 文件,校验和保证下载包是完整的,h1:哈希值(某包里所有文件一起的哈希值),go.mod h1:哈希值(某包下 mod 文件的哈希值)。
go快速入门_第14张图片

go快速入门_第15张图片

Reference

[1] https://golang.google.cn/
[2] go语言中文网
[3] 8小时转职Golang工程师
[4] Go语言后端开发如何规划学习路线?

你可能感兴趣的:(云原生,golang,开发语言,后端)