language features
Deployment is simple:
- Can be directly compiled into machine code for execution
- Does not depend on other libraries
- Deploy directly by running
- Statically typed languages: hidden problems can be detected at compile time
- Concurrency at the language level: Innate support for concurrency, making full use of multi-core
Powerful standard library:
- runtime system scheduling mechanism
- Efficient GC garbage collection
- Rich standard library
- Easy to learn: 25 keywords, support inline C syntax, object-oriented, cross-platform
Configure installation
Mac download address: https://dl.google.com/go/go1.17.3.darwin-amd64.pkg
Installation path: /usr/local/go
Configure environment variables:
vi ~/.bash_profile
export GOPATH=$HOME/go
source ~/.bash_profile
common problem
1. go.mod file not found in current directory or any parent directory
Solved: go env -w GO111MODULE=auto
Syntax Note
- It is not recommended to add a semicolon at the end of the expression
Import multiple packages
import ( "fmt" "time" )
- Function curly braces must go with the function name
vim hello.go
package main
import "fmt"
func main() {
fmt.Println("Hello Go!")
}
compile and execute
go run hello.go
compile
go build hello.go
implement
./hello
variable var
declare a variable (default value is 0)
var a int
declare a variable and initialize a value
var b int = 100
Omit the type during initialization, and automatically match the data type by value (not recommended)
var c = 100 var cc = "abcd" fmt.Printf("cc=%s,cc=%T",cc,cc)//cc=abcd,cc=string
Omit the var keyword and automatically match (commonly used)
e := 100 f := "abcd"
Remarks: Method 1.2.3 can declare global variables outside the function body; 4 can only declare local variables inside the function body
Declare a multiline variable
var xx, yy int = 100, 200 var mm, nn = 100, "abc" var ( cc int = 100 dd bool = true ) fmt.Println("cc=",cc,"dd=",dd)
constant const
Constants are not allowed to be modified
const a int = 100
const (
BEIJING = 1
SHANGHAI = 2
)
iota: used with const, each line is accumulated, the first line defaults to 0
const (
BEIJING = 10 * iota //0
SHANGHAI //10
SHENZHEN //20
)
const (
a, b = iota+1,iota+2//iota=0, a=1, b=2
c, d //iota=1, c=1, d=3
g, h = iota*2,iota*3//iota=3, g=6, h=9
)
function
basic functional form
func test(a string, b int) int {
return 100
}
Multiple return values
//匿名
func test(a string, b int) (int, int) {
return 666, 777
}
//有形参名(初始化默认为0)
func test(a string, b int) (r1 int, r2 int) {
r1 = 1000
r2 = 2000
return
}
method as parameter
func ShowBookInfoAndPrice(bookName, author string, price float64) (string, float64) {
return bookName + author, price
}
//函数式编程
func PrintBookInfo(do func(string, string, float64) (bookInfo string, finalPrice float64),
bookName, author string, price float64) {
bookInfo, finalPrice := do(bookName, author, price)
fmt.Println("bookInfo:", bookInfo)
fmt.Println("finalPrice:", finalPrice)
}
func main() {
PrintBookInfo(ShowBookInfoAndPrice, "AAA", "BBB", 99.99)
}
anonymous function
//匿名函数
func PrintBookInfo2(bookName, author string, price float64) {
do := func(string, string, float64) (bookInfo string, finalPrice float64) {
return bookName + author, price
}
fmt.Println(do(bookName, author, price))
}
func main() {
PrintBookInfo2("AAA", "BBB", 99.99)
}
variable parameter
//可变参数
func PrintBookNames(bookList ...string) {
r := ""
for _, item := range bookList {
r += item
}
fmt.Println(r)
}
func main() {
PrintBookNames("AAA", "BBB", "CCC")
}
Conditional judgment
package main
import (
"fmt"
"net/http"
)
func VisitUrl(url string) (int, error) {
res, err := http.Get(url)
defer res.Body.Close()
if err != nil {
fmt.Println("ERROR:", err)
return res.StatusCode, err
} else {
fmt.Println("OK:", res.StatusCode)
return res.StatusCode, err
}
}
func SwitchShow(url string) {
if code, err := VisitUrl(url); err != nil {
fmt.Println("Switch Error:", err)
} else {
switch code {
case 200:
fmt.Println("请求成功")
case 404:
fmt.Println("网址不存在")
default:
panic("未知错误")
}
}
}
func main() {
SwitchShow("http://www.baidu.com")
}
import and init
hello.go
package main
import (
"GoStudy/lib1"
"GoStudy/lib2"
)
func main() {
lib1.Lib1Test(); //在外部调用的函数名首字母必须大写
lib2.Lib2Test();
}
//输出结果
//lib1.init()...
//lib2.init()...
//Lib1Test()...
//Lib2Test()...
lib1/lib1.go
package lib1
import "fmt"
func Lib1Test() {
fmt.Println("Lib1Test()...")
}
func init() {
fmt.Println("lib1.init()...")
}
lib2/lib2.go
package lib2
import "fmt"
func Lib2Test() {
fmt.Println("Lib2Test()...")
}
func init() {
fmt.Println("lib2.init()...")
}
Notice:
Import an anonymous package (do not execute the functions inside the package, but execute the init method)
import _ "GoStudy/lib2"
import package alias
import l2 "GoStudy/lib2" func main() { l2.Lib2Test(); }
Import into the current package (functions can be called directly)
import . "GoStudy/lib2" func main() { Lib2Test(); }
pointer*
Note: Pointers in the GO language do not allow operations.
package main
import "fmt"
func changeValue(p *int) {
*p = 10;
}
func main() {
var a = 1
changeValue(&a)
//p = &a
//*p = 10
fmt.Println("a =",a) //a = 10
}
defer
The mechanism for executing before the end of the function (first in, last out, executed after the return method)
package main
import "fmt"
func func1() {
fmt.Println("func1()...")
}
func func2() {
fmt.Println("func2()...")
}
func func3() {
fmt.Println("func3()...")
}
func returnAndDefer() int {
defer func1()
defer func2()
defer func3()
return returnFunc()
}
func returnFunc() int {
fmt.Println("returnFunc()...")
return 0
}
func main() {
returnAndDefer()
}
//执行顺序:
returnFunc()...
func3()...
func2()...
func1()...
Arrays and Dynamic Arrays
fixed length array
package main
import "fmt"
func test(arr []int) {
arr[0] = 111
}
func main() {
//固定长度的数组
var myArr []int
//数组遍历
test(myArr)//myArr[0]不变
for k, v := range myArr2 {
fmt.Println("index=",k,"value=",v)
}
}
Dynamic arrays (slices)
Dynamic arrays are passed by reference, actually passing a pointer to the array, pointing to the same piece of memory
Dynamic array parameters of different lengths are the same
package main
import "fmt"
func test(arr []int) {
arr[0] = 111
}
func main() {
//固定长度的数组
myArr := []int{1,2,3,4}
//数组遍历
test(myArr)//myArr[0]不变
for k, v := range myArr {
fmt.Println("index=",k,"value=",v)
}
}
//输出结果
index= 0 value= 111
index= 1 value= 2
index= 2 value= 3
index= 3 value= 4
Note: _ means anonymous variable
How slices are declared
Declare slice1 as a slice, and initialize it, the default value is 1, 2, 3, and the length len is 3
slice1 := []int{1, 2, 3}
Declare slice2 to be a slice, but does not allocate space, need to allocate space (initialization value is 0)
var slice2 = []int slice2 = make([]int, 3)
Declare slice3 as a slice and allocate space via make (initialization value is 0)
var slice3 []int = make([]int, 3)
Declare slice4 as a slice and allocate space through make (initialization value is 0), deduce slice4 as a slice through := (commonly used)
slice4 := make([]int, 3)
appending of slices
len: length, indicating the distance between the left pointer and the right pointer
cap: capacity, indicating the distance from the left pointer to the end of the underlying array
Slice expansion mechanism: When appending, if the length exceeds the capacity, the capacity will be doubled (5 -> 10 -> 20)
var numbers = make([]int, 3, 5)//长度3, 容量5
fmt.Printf("len=%d,cap=%d,slice=%v",len(numbers),cap(numbers),numbers)
//len=3,cap=5,slice=[0 0 0]
Append an element 1 to numbers
numbers = append(numbers, 1)
fmt.Printf("len=%d,cap=%d,slice=%v",len(numbers),cap(numbers),numbers)
//len=4,cap=5,slice=[0 0 0 1]
Append an element 2 to numbers
numbers = append(numbers, 2)
fmt.Printf("len=%d,cap=%d,slice=%v",len(numbers),cap(numbers),numbers)
//len=5,cap=5,slice=[0 0 0 1 2]
Append elements to a full slice
numbers = append(numbers, 3)
fmt.Printf("len=%d,cap=%d,slice=%v",len(numbers),cap(numbers),numbers)
//len=6,cap=10,slice=[0 0 0 1 2 3]
cutting of slices
s := []int{1,2,3}
s1 := s[0:2]
s2 := make([]int, 3)
copy(s2, s)//将s中的值,依次copy到s2
s1[0] = 100
fmt.Println(s)//[100 2 3]
fmt.Println(s1)//[100 2]
fmt.Println(s2)//[1 2 3]
map
Declaration method
method one:
- Declare that myMap1 is a map type, the key is a string, and the value is a string
- Before using map, you need to use make to allocate data space to map
var myMap1 map[string]string myMap1 = make(map[string]string, 10) myMap1["a"] = "aaa" myMap1["b"] = "bbb"
Method two:
myMap2 := make(map[int]string) myMap2[0] = "a" myMap2[1] = "b" fmt.Println(myMap2) //map[0:a 1:b]
way three
myMap3 := map[int]string { 0 : "a", 1 : "b", } fmt.Println(myMap3) //map[0:a 1:b]
How to use
Map is also passed by reference, and the pointer address is passed when it is used as a parameter.
Add to
myMap2 := make(map[int]string) myMap2[0] = "a" myMap2[1] = "b"
traverse
for k, v := range myMap2 { fmt.Printf("k=%d,v=%s\n",k,v) }
delete
delete(myMap2, 0)
Revise
myMap2[0] = "c"
object oriented
structure
definition
type Book struct { title string //类的属性首字母大写表示公有,否则为私有 auth string }
use
var book1 Book book1.title = "Golang" book1.auth = "Tom" fmt.Println(book1)//{Golang Tom} book2 := Book{title:"aaa",auth:"bbb"} fmt.Println(book2)//{aaa bbb} book3 := Book{"aaa","bbb"} fmt.Println(book3)//{aaa bbb}
Pass (pass is a copy)
func changeBook(book Book) { book.title="XXX" } func main() { var book1 Book book1.title = "Golang" book1.auth = "Tom" changeBook(book1) fmt.Println(book1)//{Golang Tom} }
kind
Encapsulation: class name, attribute name, method name with the first letter capitalized to indicate that it can be accessed externally
this is a copy (copy) of the object on which the method was called
func (this *Book) setName(title string) {
this.title=title
}
func (this Book) setAuth(auth string) {
this.auth=auth
}
func main() {
book := Book{title:"aaa",auth:"bbb"}
book.setName("ccc")
book.setAuth("ddd")
fmt.Println(book)//{ccc bbb}
}
inherit
package main
import "fmt"
type Human struct {
name string
sex string
}
type SuperMan struct {
Human
level int
}
func (this *Human) Eat() {
fmt.Println("Human Eat...")
}
func (this *Human) Walk() {
fmt.Println("Human Walk...")
}
func (this *SuperMan) Walk() {
fmt.Println("SuperMan Walk...")
}
func (this *SuperMan) Fly() {
fmt.Println("SuperMan Fly...")
}
func main() {
tom := Human{"aaa","bbb"}
tom.Eat() //Human Eat...
tom.Walk()//Human Walk...
//s :=SuperMan{Human{"ccc","ddd"},100}
var s SuperMan
s.name = "Sss"
s.sex = "man"
s.level= 88
s.Walk()//SuperMan Walk...
s.Fly()//SuperMan Fly...
}
polymorphism
The interface is essentially a pointer to the parent class
Basic elements:
- has a parent class (interface)
- There are subclasses that implement all the interface methods of the parent class
- A variable (pointer) of the superclass type points (references) to a specific data variable of the subclass
package main
import "fmt"
type AnimalIF interface {
Sleep()
GetColor() string
}
type Cat struct {
color string
}
func (this *Cat) Sleep() {
fmt.Println("Cat Sleep...")
}
func (this *Cat) GetColor() string {
return this.color
}
type Dog struct {
color string
}
func (this *Dog) Sleep() {
fmt.Println("Dog Sleep...")
}
func (this *Dog) GetColor() string {
return this.color
}
func showAnimal(animal AnimalIF) {
animal.Sleep()
fmt.Println("color=",animal.GetColor())
}
func main() {
var animal AnimalIF//接口的数据类型:父类指针
animal = &Cat{"White"}
animal.Sleep()//Cat Sleep...
fmt.Println("color=",animal.GetColor())//color= White
dog := Dog{"Yellow"}
showAnimal(&dog)
//Dog Sleep...
//color= Yellow
}
Universal data type interface{} (empty interface)
interface{} type assertion mechanism: arg.(string)
package main
import "fmt"
type Book struct {
tile string
}
func test(arg interface{}){
fmt.Println(arg)
//断言
_, ok := arg.(string)
if !ok {
fmt.Println("arg is not string")
}else{
fmt.Println("arg is string")
}
}
func main() {
book := Book{"Golang"}
test(book)//{Golang}
test(123)//123
test("hello")//hello
}
variable type
variable pair
type
- static type: int/string
- Concrete type: The specific data type that the interface refers to (the type visible to the system runtime)
- value
package main
import "fmt"
type Reader interface {
ReadBook()
}
type Writer interface {
WriteBook()
}
type Book struct {
}
func (this *Book) ReadBook() {
fmt.Println("Read a book.")
}
func (this *Book) WriteBook() {
fmt.Println("Write a book.")
}
func main() {
b := &Book{}//b: pair<type:Book, value:Book{}地址>
var r Reader//r: pair<type: 空, value: 空>
r = b //r: pair<type:Book, value:Book{}地址>
r.ReadBook()
var w Writer
w = r.(Writer)//w: pair<type:Book, value:Book{}地址>
//断言有两步:得到动态类型 type,判断 type 是否实现了目标接口。
//这里断言成功是因为 type 是 Book,而 Book 实现了 Writer 接口
w.WriteBook()
}
reflection
example 1:
package main
import (
"fmt"
"reflect"
)
func reflectNum(arg interface{}){
fmt.Println("type:", reflect.TypeOf(arg))
fmt.Println("value:", reflect.ValueOf(arg))
}
func main() {
var num float64 = 1.34556
reflectNum(num)
//type: float64
//value: 1.34556
}
Example 2:
package main
import (
"fmt"
"reflect"
)
type User struct {
Id int
Name string
Age int
}
func (this User) Call(){
fmt.Printf("User: %v", this)
}
func DoFieldAndMethod(input interface{}){
inputType := reflect.TypeOf(input)
inputValue := reflect.ValueOf(input)
//遍历属性
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)
}
//Id:int
//Name:string = Lilei
//Age:int = 18
//遍历方法(注意指针类型的结构体方法无法打印)
for i := 0; i < inputType.NumMethod(); i++ {
inputMethod := inputType.Method(i)
fmt.Printf("%s:%v\n",inputMethod.Name, inputMethod.Type)
}
//Call:func(main.User)
}
func main() {
user := User{1, "Lilei", 18}
DoFieldAndMethod(user)
}
Structure Tag Tag
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string `info:"name" doc:"姓名"`
Age int `info:"age" doc:"年龄"`
}
func findTag(input interface{}){
inputType := reflect.TypeOf(input).Elem()
//遍历属性
for i := 0; i < inputType.NumField(); i++ {
taginfo := inputType.Field(i).Tag.Get("info")
tagdoc := inputType.Field(i).Tag.Get("doc")
fmt.Printf("info:%s doc:%s\n",taginfo, tagdoc)
}
}
func main() {
var u User
findTag(&u)
//info:name doc:姓名
//info:age doc:年龄
}
Application of structure tags in json
package main
import (
"fmt"
"encoding/json"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Hobby []string `json:"hobby"`
}
func main() {
user := User{"lilei", 18, []string{"dance","football"}}
//json编码
jsonStr, err := json.Marshal(user)
if err != nil {
fmt.Println("Json marshal error.")
return
}
fmt.Printf("json = %s",jsonStr)//json = {"name":"lilei","age":18,"hobby":["dance","football"]}
//json解码
user1 := User{}
err = json.Unmarshal(jsonStr, &user1)
if err != nil {
fmt.Println("Json unmarshal error.")
return
}
fmt.Println(user1)//{lilei 18 [dance football]}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。