Go 语言入门指南 | 青训营
1.1 什么是Go语言
Go语言具有高性能、高并发;语法简单、学习曲线平缓;丰富的标准库;完善的工具链;静态连接;快速编译;跨平台;垃圾回收等特点
2.2 基础语法
例子1 Hello World
package main
import {
"fmt"
}
func main(){
fmt.Println("hello world")
}
packgae main代表文件是main包的一部分,main包是入口函数,程序从此处开始运行
import { “fmt” }导入了go标准库中的fmt包,用于格式化文本并将其输出到标准输出或文件中,其中常用的函数如下所示:
fmt.Print()——该函数用于将文本打印到控制台
fmt.Printf()——该函数用于格式化文本并将其打印到控制台
fmt.Println()——该函数用于将文本打印到控制台,并在后面加上一个换行符
fmt.Sprintf()——该函数用于格式化文本并将其作为字符串返回
fmt.Errorf()——该函数用于创建具有格式化文本的错误信息
fmt.Scan()——该函数用于从控制台扫描输入并将其解析为不同类型的数据
fmt.Sprint()——该函数用于将数据格式化为字符串并返回
func main(){ }定义了main函数,函数中调用fmt.Println来输出“hello world”
直接运行文件
go run example/01-hello/main.go
编译成二进制后运行
go build example example/01-hello/main.go
./main
例子2 变量
Go中常见的变量类型包括字符串(内置类型,可以通过'+'拼接,'='直接比较两个字符串)、整数、浮点型、布尔型,运算符优先级类似于C++/C语言,如下所示。
| 运算符名称 | 符号 |
|---|
| 括号 | () |
| 自增自减 | ++, -- |
| 单目运算符 | +, -, !, ^, & |
| 乘除模运算 | /, %, * |
| 加法和减法 | +,- |
| 移位运算符 | <<, >> |
| 按位与 | & |
| 按位异或 |
| 按位或 | | |
| 关系运算符 | ==, !=, <, <=, >, >= |
| 逻辑运算符 | &&, || |
| 赋值运算符 | =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= |
package main
import {
"fmt"
"math"
}
func main() {
var a = "initial"
var b, c int = 1, 2
var d = true
var e float64
f := float32(e)
g := a + "foo"
fmt.Println(a, b, c, d, e, f)
fmt.Println(g)
const s string = "constant"
const h = 500000000
const i = 3e20 / h
fmt.Println(s, h, i, math.Sin(h), math.Sin(i))
}
变量标准格式声明:var 变量名 变量类型当一个变量被声明后,系统自动赋予它该类型的零值或空值,例如: int类型为0,float类型为0.0,bool类型为flase,string类型为空字符串,指针类型为nil等;
变量的批量格式声明:使用关键字var和括号将一组变量定义放在一起,示例如下:
var (
name string
age int
price float32
)
变量的简短格式声明:变量名 := 表达式这种声明方式会自己辨别类型,但有如下限制:
- 只能用来定义变量,同时会显示初始化
- 不能提供数据类型
- 只能用在函数内部,即不能用来声明全局变量
变量的赋值:var 变量名 [类型] = 变量值,批量赋值方式var( 变量名1 (变量类型1) = 变量值1 变量名2 (变量类型2) = 变量值2 // ...省略),示例如下:
# 显示标准格式赋值
var b int = 1
# 隐式标准格式赋值
var a = "initial"
# 简短格式赋值
f := float32(e)
# 批量赋值标准格式
var (
title string = "Go 语言基础篇“
content string = "这里是青训营"
author string = "字节跳动"
)
# 多变量同一行赋值
var b, c int = 1, 2
# 简单形式
var b, c := 1, 2
常量const 变量名 = 变量值没有确定的类型
例子3 if else
package main
import "fmt"
func main() {
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
if 8%4 ==0 {
fmt.Println("8 is divisible by 4")
}
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")
}
}
例子4 循环
package main
import "fmt"
func main() {
i := 1
for {
fmt.Println("loop")
break
}
for j := 7; j < 9; j++ {
fmt.Println(j)
}
for n := 0; n < 5; n++ {
if n%2 ==0 {
continue
}
fmt.Println(n)
}
for i <= 3 {
fmt.Println(i)
i = i + 1
}
}
例子5 switch
package main
import {
"fmt"
"time"
}
func main(){
a := 2
switch a {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
case 4, 5:
fmt.Println("four or five")
default:
fmt.Println("other")
}
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
}
Go中不用单独加入break,运行完自动跳出,支持任意变量类型来进行switch操作
例子6 数组
packgae main
import "fmt"
func main() {
var a [5]int
a[4] = 100
fmt.Println(a[4], len(a))
b := [5]int{1, 2, 3, 4, 5}
fmt.Println(b)
var twoD [2][3]int
for i := 0; i <2; i++ {
for j := 0; j < 3; j++ {
twoD[i][j] = i + j
}
}
fmt.Println("2d: ", twoD)
}
例子7 切片
package main
import "fmt"
func main() {
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("get:", s[2])
fmt.Println("len:", len(s))
s = append(s, "d")
s = append(s, "e", "f")
fmt.Println(s)
c := make([]string, len(s))
copy(c, s)
fmt.Println(c)
fmt.Println(s[2:5])
fmt.Println(s[:5])
fmt.Println(s[2:])
good := []string{"g", "o", "o", "d"}
fmt.Println(good)
}
不同于数组,长度不限制,可以类似数组一样操作,用append来追加元素,但需要赋值给原先的切片。
例子8 map
package main
import "fmt"
func main() {
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m)
fmt.Println(len(m))
fmt.Println(m["one"])
fmt.Println(m["unknow"])
r, ok := m["unknow"]
fmt.Println(r, ok)
delete(m, "one")
m2 := map[string]int{"one": 1, "two": 2}
var m3 = map[string]int{"one": 1, "two": 2}
fmt.Println(m2, m3)
}
使用最频繁的数据结构,map是无序的
例子9 range
package main
import "fmt"
func main() {
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num)
}
}
fmt.Println(sum)
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
fmt.Println(k, v)
}
for k := range m {
fmt.Println("key", k)
}
}
可以用range来快速遍历
例子10 函数
package main
import "fmt"
func add(a int, b int) int {
return a + b
}
func add2(a, b int) int {
return a + b
}
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
func main() {
res := add(1, 2)
fmt.Println(res)
v, ok := exists(map[string]string{"a": "A"}, "a")
fmt.Println(v, ok)
}
真实业务场景中函数一般返回两个值,第一个值为value,第二个值是错误信息
例子11 指针
package main
import "fmt"
func add2(n int) {
n += 2
}
func add2ptr(n *int) {
*n += 2
}
func main() {
n := 5
add2(n)
fmt.Println(n)
add2ptr(&n)
fmt.Println(n)
}
指针操作有限,起到指向位置的作用
例子12 结构体
package main
import "fmt"
type user struct {
name string
password string
}
func main() {
a := user{name: "wang", password: "1024"}
b := user{"wang", "1024"}
c := user{name: "wang"}
c.password = "1024"
var d user
d.name = "wang"
d.password = "1024"
fmt.Println(a, b, c, d)
fmt.Println(checkPassword(a, "haha"))
fmt.Println(checkPassword2(&a, "haha"))
}
func checkPassword(u user, password string) bool {
return u.password == password
}
func checkPassword2(u *user, password string) bool {
return u.password == password
}
结构体是字段的集合,初始化可以指定部分字段值或者为空值,可以用指针来避免结构体赋值运用导致的内存占用
例子13 结构体方法
package main
import "fmt"
type user struct {
name string
password string
}
func (u user) checkPassword(password string) bool {
return u.password == password
}
func (u *user) resetPassword(password string) {
u.password = password
}
func main() {
a := user{name: "wang", password: "1024"}
a.resetPassword("2048")
fmt.Println(a.checkPassword("2048"))
}
为结构体定义方法,类似类操作
例子14 错误处理
package main
import (
"errors"
"fmt"
)
type user struct {
name string
password string
}
func findUser(users []user, name string) (v *user, err error) {
for _, u := range users {
if u.name == name {
return &u, nil
}
}
return nil, errors.New("not found")
}
func main() {
u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name)
if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err)
return
} else {
fmt.Println(u.name)
}
}
函数的返回值中加入error,如果有错误用error.New来创建
例子15 字符串操作
package main
import (
"fmt"
"strings"
)
func main() {
a := "hello"
fmt.Println(strings.Contains(a, "ll"))
fmt.Println(strings.Count(a, "l"))
fmt.Println(strings.HasPrefix(a, "he"))
fmt.Println(strings.HasSuffix(a, "llo"))
fmt.Println(strings.Index(a, "ll"))
fmt.Println(strings.Join([]string{"he", "llo"}, "-"))
fmt.Println(strings.Repeat(a, 2))
fmt.Println(strings.Replace(a, "e", "E", -1))
fmt.Println(strings.Split("a-b-c", "-"))
fmt.Println(strings.ToLower(a))
fmt.Println(strings.ToUpper(a))
fmt.Println(len(a))
b := "你好"
fmt.Println(len(b))
}
stings包中包含许多字符串的操作,详细总结如下:
package main
import (
"strings"
"fmt"
)
func main() {
fmt.Println(strings.EqualFold("tiger","tiger"))
fmt.Println(strings.EqualFold("TiGer","tiger"))
fmt.Println(strings.EqualFold("Tiger","ger"))
fmt.Println(strings.EqualFold("TiGer-123","tiger-123"))
fmt.Println(strings.TrimSpace(" hello world !! "))
fmt.Println(strings.HasPrefix("hello world!!","he"))
fmt.Println(strings.HasSuffix("hello golang","lang"))
fmt.Println(strings.HasSuffix("hello golang","ng"))
fmt.Println(strings.Index("hello golang","ll"))
fmt.Println(strings.Index("hello golang","nihao"))
fmt.Println(strings.LastIndex("hello golang","o"))
fmt.Println(strings.Replace("hello golang hello python hello shell","ll","ww",0))
fmt.Println(strings.Replace("hello golang hello python hello shell","ll","ww",1))
fmt.Println(strings.Replace("hello golang hello python hello shell","ll","ww",2))
fmt.Println(strings.Replace("hello golang hello python hello shell","ll","ww",-1))
fmt.Println(strings.Title("hello golang"))
fmt.Println(strings.ToTitle("hello golang nihao"))
fmt.Println(strings.ToLower("HELLO GOLANG NIHAO"))
fmt.Println(strings.ToTitle("hello golang nihao"))
fmt.Println(strings.Contains("hello golang","golang"))
fmt.Println(strings.Contains("hello golang","nihao"))
fmt.Println(strings.Contains("hello golang","GOLANG"))
fmt.Println(strings.ContainsAny("hello Golang","g"))
fmt.Println(strings.ContainsAny("hello Golang","l & a"))
fmt.Println(strings.ContainsAny("Shell-12345","1-2"))
fmt.Println(strings.Contains("Shell-12345","1-2"))
fmt.Println(strings.Count("ttiger","t"))
fmt.Println(strings.Count("ttiger","m"))
textString := "golang"
fmt.Println(strings.Repeat(textString,5))
fmt.Println("ba" + strings.Repeat("na",2))
fmt.Println("ba" + strings.Repeat(" ",2))
fmt.Println("22" + strings.Repeat("11",2))
fmt.Println(strings.Trim("01234 56780","0"))
fmt.Println(strings.Trim("01234 56789","0"))
fmt.Println(strings.TrimLeft("abcd efg","a"))
fmt.Println(strings.TrimRight("abcd efg","g"))
s := "i love china"
fmt.Println(strings.TrimPrefix(s,"i"))
testString := "i love china"
testArray := strings.Fields(testString)
fmt.Println("testArray=",testArray)
for _, v := range testArray {
fmt.Println(v)
}
fmt.Println(strings.ContainsRune("geeksforgeeks",97))
news := "qwert"
fmt.Println(strings.Split(news,""))
fmt.Println("news=",news)
for k,v := range strings.Split(news,"") {
fmt.Println(k,v)
}
a := "/../"
fmt.Println(strings.Split(a,"/"))
path := []string{"aa","bb","cc"}
fmt.Println(strings.Join(path,"/"))
}
例子16 字符串格式化
package main
import "fmt"
type point struct {
x, y int
}
func main() {
s := "hello"
n := 123
p := point{1, 2}
fmt.Println(s, n)
fmt.Println(p)
fmt.Printf("s=%v\n", s)
fmt.Printf("n=%v\n", n)
fmt.Printf("p=%v\n", p)
fmt.Printf("p=%+v\n", p)
fmt.Printf("p=%#v\n", p)
f := 3.141592653
fmt.Println(f)
fmt.Printf("%.2f\n", f)
}
例子17 JSON处理
package main
import (
"encoding/json"
"fmt"
)
type userInfo struct {
Name string
Age int `json:"age"`
Hobby []string
}
func main() {
a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
buf, err := json.Marshal(a)
if err != nil {
panic(err)
}
fmt.Println(buf)
fmt.Println(string(buf))
buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(buf))
var b userInfo
err = json.Unmarshal(buf, &b)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", b)
}
首字母大写
例子18 时间处理
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
fmt.Println(now)
t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)
t2 := time.Date(2022, 3, 27, 2, 30, 36, 0, time.UTC)
fmt.Println(t)
fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute())
fmt.Println(t.Format("2006-01-02 15:04:05"))
diff := t2.Sub(t)
fmt.Println(diff)
fmt.Println(diff.Minutes(), diff.Seconds())
t3, err := time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:36")
if err != nil {
panic(err)
}
fmt.Println(t3 == t)
fmt.Println(now.Unix())
}
例子19 数字解析
package main
import (
"fmt"
"strconv"
)
func main() {
f, _ := strconv.ParseFloat("1.234", 64)
fmt.Println(f)
n, _ := strconv.ParseInt("111", 10, 64)
fmt.Println(n)
n, _ = strconv.ParseInt("0x1000", 0, 64)
fmt.Println(n)
n2, _ := strconv.Atoi("123")
fmt.Println(n2)
n2, err := strconv.Atoi("AAA")
fmt.Println(n2, err)
}
解析字符串,第一个字符串,第二个是进制,第三个是位数
例子20 进程信息
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
fmt.Println(os.Args)
fmt.Println(os.Getenv("PATH"))
fmt.Println(os.Setenv("AA", "BB"))
buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()
if err != nil {
panic(err)
}
fmt.Println(string(buf))
}