Golang基础学习笔记
1、下载安装
1.1、下载
Golang下载地址:https://golang.google.cn/dl/
1.2、安装
1.3、环境变量
# GOPATH
D:\GolandProjects
# Path
%GOROOT%\bin
# 启用Go模块支持
go env -w GO111MODULE=on
# 配置Go模块下载代理
go env -w GOPROXY=https://goproxy.cn,direct
1.5、验证安装/配置
1.5、hello world
2、变量/常量
2.1、变量
package main
import "fmt"
func main() {
// var 变量名字 类型 = 表达式
// 单个变量定义
//var name string = "xumeng03!"
//var name = "xumeng03!"
//name := "xumeng03!"
var name string
name = "xumeng03"
fmt.Println("hello", name)
// 多个变量定义
//var name1, name2 = "xumeng", "xumeng03"
var (
name1 = "xumeng03"
name2 = "xumeng"
)
fmt.Println("hello", name1, name2)
}
2.2、常量
package main
import "fmt"
func main() {
// const 变量名字 类型 = 表达式
const name string="xumeng03"
// 报错
//name = "xumeng"
//const name1 string
//name1 = "aaa"
fmt.Println("hello", name)
}
3、基本数据类型
3.1、基本类型
数据类型 | 类型解释 | 默认零值 | 示例 | 传递 |
---|---|---|---|---|
bool | 布尔型,值为true 或false | false | var vbool bool = true | 值 |
uint8 | 8位无符号整型,取值范围为0到255 | 0 | var vuint8 uint8 = 1 | 值 |
uint16 | 16位无符号整型,取值范围为0到65535 | 0 | var vuint16 uint16 = 1 | 值 |
uint32 | 32位无符号整型,取值范围为0到4294967295 | 0 | var vuint32 uint32 = 1 | 值 |
uint64 | 64位无符号整型,取值范围为0到4294967295 | 0 | var vuint64 uint64 = 1 | 值 |
uint | 32位/64位无符号整型,具体位数与操作系统有关 | var vuint uint = 1 | 值 | |
int8 | 8位有符号整型,取值范围为-128到127 | 0 | var vint8 int8 = 2 | 值 |
int16 | 16位有符号整型,取值范围为-32768到32767 | 0 | var vint16 int16 = 2 | 值 |
int32 | 32位有符号整型,取值范围为-2147483648到2147483647 | 0 | var vint32 int32 = 2 | 值 |
int64 | 64位有符号整型,取值范围为-9223372036854775808到9223372036854775807 | 0 | var vint64 int64 = 2 | 值 |
int | 32位/64位有符号整型,具体位数与操作系统有关 | var vint int = 2 | 值 | |
float32 | 32位浮点型,可以表示小数,精度为7位小数 | 0 | var vfloat32 float32 = 3.14 | 值 |
float64 | 64位浮点型,可以表示小数,精度为15位小数 | 0 | var vfloat64 float64 = 3.14 | 值 |
string | 字符串类型,由一串Unicode码点组成 | “” | var vstring string = “hello world!” | 值 |
package main
import (
"fmt"
"math"
"strconv"
)
func main() {
// bool
var vbool bool
fmt.Printf("类型: %T,默认值: %t\n", vbool, vbool)
// uint8、uint16、uint32、uint64(uint)
var vuint uint
var vuint8 uint8
var vuint16 uint16
var vuint32 uint32
var vuint64 uint64
fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vuint, vuint, 0, strconv.FormatUint(math.MaxUint, 10))
fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vuint8, vuint8, 0, math.MaxUint8)
fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vuint16, vuint16, 0, math.MaxUint16)
fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vuint32, vuint32, 0, math.MaxUint32)
fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vuint64, vuint64, 0, strconv.FormatUint(math.MaxUint64, 10))
// int8、int16、int32、int64
var vint int
var vint8 int8
var vint16 int16
var vint32 int32
var vint64 int64
fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vint, vint, math.MinInt, math.MaxInt)
fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vint8, vint8, math.MinInt8, math.MaxInt8)
fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vint16, vint16, math.MinInt16, math.MaxInt16)
fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vint32, vint32, math.MinInt32, math.MaxInt32)
fmt.Printf("类型: %T,默认值: %d,最小值: %d,最大值: %d\n", vint64, vint64, math.MinInt64, math.MaxInt64)
// float32、float64
var vfloat32 float32
var vfloat64 float64
fmt.Printf("类型: %T,默认值: %f\n", vfloat32, vfloat32)
fmt.Printf("类型: %T,默认值: %f\n", vfloat64, vfloat64)
// string(值传递)
var vstring string
fmt.Printf("类型: %T,默认值: %s\n", vstring, vstring)
}
3.2、基本类型转换
只有类型兼容的才可以转换!
package main
import (
"fmt"
)
func main() {
var vint8 int8
var vint16 int16
//vint16 = vint8;
vint16 = int16(vint8);
fmt.Printf("类型: %T,值: %d", vint16, vint16)
// 大转小会有精度丢失问题
//var vint8 int8
//var vint16 int16 = 257
//vint8 = int8(vint16)
//fmt.Printf("类型: %T,值: %d", vint8, vint8)
}
4、复合数据类型
数据类型 | 类型解释 | 默认值 | 示例 | 传递 |
---|---|---|---|---|
Array | 相同类型且长度固定的数据集合 | [0,0,0] | var arr1 = [3]int{1, 2, 3} | 值 |
Slice | 相同类型且长度不固定的数据集合(底层是数组,也被称为动态数组) | [] | var sli1= []int{1, 2, 3} | 引用 |
Map | 键值对 | [] | var m = map[string]string{“ke y”: “value”} | 引用 |
Func | 函数类型 | - | - | 引用 |
Pointer | 指针类型 | - | - | 值/引用 |
Struct | 结构体类型 | - | - | 值 |
Interface | 接口类型 | - | - | - |
4.1、Array(数组)
1、初始化
package main
import (
"fmt"
)
func main() {
// 一维数组
// 方法1:声明并初始化一个固定长度的数组
// 方法2:使用数组字面量初始化数组
var arr2 = [3]int{1, 2, 3}
// 方法3:省略数组长度的方式初始化数组
var arr3 = [...]int{1, 2, 3, 4, 5, 6, 7}
// 方法4:省略数组长度的方式并使用索引初始化数组
var arr4 = [...]int{2: 3, 4: 5}
fmt.Println(arr1, arr2, arr3, arr4)
// 二维数组
var arr5 = [3][5]int{{2: 3, 4: 5}, {1, 2, 3, 4}, {1, 2, 3, 4}}
fmt.Println(arr5)
}
2、遍历
package main
func main() {
var arr = [...]int{1, 2, 3, 4, 5, 6, 7}
// 方法1:for range
for index, value := range arr {
print("arr[", index, "]==", value, ",")
}
println()
// 方法2:fori
for index := 0; index < len(arr); index++ {
print("arr[", index, "]==", arr[index], ",")
}
}
3、数组操作
package main
import "fmt"
func main() {
var arr1 = [3]int{1, 2, 3}
// 获取数组长度
fmt.Println(arr1, len(arr1))
// 获取元素
fmt.Println(arr1[0])
// 修改元素
arr1[0] = 101
fmt.Println(arr1)
}
4.2、Slice(切片)
1、定义
package main
import (
"fmt"
)
func main() {
// 一维切片
// 方法1:声明并初始化一个切片
var slice1 []int
fmt.Println(slice1)
// 方法2:使用切片字面量初始化数组
var slice2 = []int{1, 2, 3, 4, 5, 6, 7}
fmt.Println(slice2)
// 方法3:使用make函数初始化
var slice3 = make([]int, 8)
fmt.Println(slice3)
// 方法4:通过数组创建切片,中括号中左开右闭(左侧不填默认为0,右侧不填默认数组长度)
var arr1 = [3]int{1, 2, 3}
slice4 := arr1[1:2]
fmt.Println(slice4)
// 方法5:通过切片创建切片
slice5 := slice2[:3]
fmt.Println(slice5)
// 方法6:拼接切片创建切片
slice6 := append(slice4, slice5...)
fmt.Println(slice6)
// 二维数组
var slice7 = [][]int{{2: 3, 4: 5}, {1, 2, 3, 4}, {1, 2, 3, 4}}
fmt.Println(slice7)
}
2、遍历
package main
func main() {
var slice1 = []int{1, 2, 3, 4, 5, 6, 7}
// 方法1:for range
for index, value := range slice1 {
print("arr[", index, "]==", value, ",")
}
println()
// 方法2:fori
for index := 0; index < len(slice1); index++ {
print("arr[", index, "]==", slice1[index], ",")
}
}
3、切片操作
package main
import (
"fmt"
)
func main() {
var slice1 = []int{1, 2, 3, 4, 5, 6, 7}
// 切片长度,切片容量
fmt.Println(slice1, len(slice1), cap(slice1))
// 追加元素
slice1 = append(slice1, 8)
fmt.Println(slice1, len(slice1), cap(slice1))
// 修改元素
slice1[7] = 80
fmt.Println(slice1, len(slice1), cap(slice1))
// 拷贝切片
var slice2 = make([]int, len(slice1))
copy(slice2, slice1) // 深拷贝,可指定索引
slice3 := slice1 // 浅拷贝
slice1[6] = 70
fmt.Println(slice1, len(slice1), cap(slice1))
fmt.Println(slice2, len(slice2), cap(slice2))
fmt.Println(slice3, len(slice3), cap(slice3))
}
4.3、Map(映射)
1、定义
package main
import "fmt"
func main() {
// 方法1:声明一个Map
var map1 map[string]string
fmt.Println(map1)
// 方法2:使用map字面量初始化Map
var map2 = map[string]string{"name": "xumeng03"}
fmt.Println(map2)
// 方法3:使用make函数初始化
var map3 = make(map[string]string)
fmt.Println(map3)
}
2、遍历
package main
import "fmt"
func main() {
var map1 = map[string]string{"name": "xumeng03", "age": "23"}
for key, value := range map1 {
fmt.Println(key, value)
}
}
3、map操作
package main
import "fmt"
func main() {
var map1 = map[string]string{"name": "xumeng03"}
fmt.Println(map1)
// 获取值
fmt.Println(map1["name"])
// 添加值(如果值存在则为更新)
map1["age"] = "23"
fmt.Println(map1)
// 判断key是否存在
_, exits := map1["address"]
fmt.Println(exits)
// 删除
delete(map1, "age")
fmt.Println(map1)
// 长度
fmt.Println(len(map1))
}
4.4、Func(函数)
package main
import "fmt"
func main() {
_m, _n, _result := add(1, 10)
fmt.Println(_m, _n, _result)
fmt.Printf("%T\n", add)
}
func add(m, n int) (_m, _n, _result int) {
result := 0
for i := m; i <= n; i++ {
result += i
}
return m, n, result
}
4.5、Point(指针)
package main
import "fmt"
func main() {
// &表取地址,*表取值
a := 10
fmt.Printf("a的值是%d,a的数据类型是%T,a的地址是%p\n", a, a, &a)
p := &a
fmt.Printf("p的地址是%p,p的数据类型是%T,p地址的数据是%d\n", p, p, *p)
p1 := &p
fmt.Printf("p1的地址是%p,p1的数据类型是%T,p1地址的数据是%p\n", p1, p1, *p1)
}
4.6、Struct(结构体)
package main
import "fmt"
func main() {
// 方法1:声明并初始化Person
var p1 Person = Person{}
p1.name = "xumeng03"
p1.age = 23
p1.sex = true
p1.address = "shanghai"
fmt.Println(p1)
// 方法2:使用字面量初始化Person
var p2 = Person{
"xumeng03", 23, true, "shanghai",
}
fmt.Println(p2)
// 方法3:使用字面量初始化Person部分属性
var p3 = Person{
name: "xumeng03",
}
fmt.Println(p3)
}
type Person struct {
name string
age int
sex bool
address string
}
4.7、接口
package main
import "fmt"
func main() {
var j = JuniorHighStudent{
name: "xumeng02",
}
study(j, "物理")
var h = HighStudent{
name: "xumeng03",
}
study(h, "化学")
}
type IStudent interface {
study(name string) string
}
type HighStudent struct {
name string
}
type JuniorHighStudent struct {
name string
}
func (j JuniorHighStudent) study(name string) string {
return j.name + " study " + name
}
func (j HighStudent) study(name string) string {
return j.name + " study " + name
}
func study(iStudent IStudent, name string) {
fmt.Println(iStudent.study(name))
}
5、运算符
5.1、算数运算符
package main
import (
"fmt"
)
func main() {
a := 9
b := 3
fmt.Printf("%d + %d = %d\n", a, b, a+b)
fmt.Printf("%d - %d = %d\n", a, b, a-b)
fmt.Printf("%d * %d = %d\n", a, b, a*b)
fmt.Printf("%d / %d = %d\n", a, b, a/b)
fmt.Printf("%d %% %d = %d\n", a, b, a%b)
c := 3
c++
fmt.Printf("%d\n", c)
c--
fmt.Printf("%d", c)
}
5.2、关系运算符
package main
import (
"fmt"
)
func main() {
a := 9
b := 3
c := 3
fmt.Printf("%d > %d ? %t\n", a, b, a > b)
fmt.Printf("%d < %d ? %t\n", a, b, a < b)
fmt.Printf("%d == %d ? %t\n", a, b, a == b)
fmt.Printf("%d >= %d ? %t\n", b, b, b >= c)
fmt.Printf("%d <= %d ? %t\n", a, b, a <= b)
fmt.Printf("%d != %d ? %t\n", b, b, b != c)
}
5.3、逻辑运算符
func main() {
a := 9
b := 3
c := 3
fmt.Printf("%b & %d = %b\n", a, b, b, c, a > b && b == c)
fmt.Printf("%d < %d || %d == %d ? %t\n", a, b, b, c, a < b || b != c)
}
5.4、位运算符
package main
import (
"fmt"
)
func main() {
a := 9
b := 3
// 对应位均为1,才是1,否则为0
fmt.Printf("%b & %b = %b\n", a, b, a&b)
// 对应位均为0,才是0,否则为1
fmt.Printf("%b | %b = %b\n\n", a, b, a|b)
// 对应位值不同为1,否则为0
fmt.Printf("%b ^ %b = %b\n", a, b, a^b)
// 按位取反
fmt.Printf("^%b = %b\n", a, ^a)
// 对于b的值,如果为0,则取a对应位的值,否则取0
fmt.Printf("%b &^ %b = %b\n", a, b, a&^b)
// a=a*2^2
a = a << 2
fmt.Printf("9 << 2 = %b(%d)\n", a, a)
// a=a/2
a = a >> 1
fmt.Printf("36 >> 1 = %b(%d)\n", a, a)
}
5.5、赋值运算符
package main
import (
"fmt"
)
func main() {
a := 9
b := 3
a += b
fmt.Printf("9 + 3 = %d\n", a)
a -= b
fmt.Printf("12 - 3 = %d\n", a)
}
6、输入/输出
6.1、输出
方法 | 说明 |
---|---|
fmt.Print | 将参数打印输出到标准输出,不进行格式化处理,参数之间用空格分隔 |
fmt.Println | 将参数打印输出到标准输出,不进行格式化处理,参数之间用空格分隔,并在最后添加换行符 |
fmt.Printf | 通过格式化字符串和参数进行输出。格式化字符串中可以包含占位符(例如%s 、%d 等),用于指定参数的格式和位置 |
fmt.Sprintf | 通过格式化字符串和参数生成一个格式化后的字符串,而不是直接打印输出。返回生成的字符串,可以赋值给变量或作为其他函数的参数 |
package main
import "fmt"
func main() {
a := 11
fmt.Printf("类型: %T,值: %d,二进制值 %b,八进制值 %o,十进制值 %d,十六进制值 %x,十六进制值 %X\n", a, a, a, a, a, a, a)
b := "xumeng03"
fmt.Printf("类型: %T,值: %s\n", b, b)
c := 'A'
fmt.Printf("类型: %T,值: %c\n", c, c)
d := ""
fmt.Printf("类型: %T,地址: %p\n", d, &d)
}
6.2、输入
方法 | 说明 |
---|---|
fmt.Scan | 从标准输入中读取输入,并将解析后的值存储到指定的变量中。它需要传入指向变量的指针作为参数,并以空格为分隔符进行解析 |
fmt.Scanf | 从标准输入中按照指定的格式字符串读取输入,并将解析后的值存储到指定的变量中。 |
package main
import (
"fmt"
"strconv"
)
func main() {
//fmt.Print("请输入名称: ")
//var a string
//fmt.Scan(&a)
//fmt.Println("hello", a+"!")
fmt.Print("请输入名称、年龄: ")
var a string
var b int64
fmt.Scanf("%s %d", &a, &b)
fmt.Println("hello", a+" "+strconv.FormatInt(b, 10)+"!")
}
7、流程控制
7.1、判断语句
1、if
package main
import (
"fmt"
)
func main() {
fmt.Print("请输入年龄: ")
var b int64
//fmt.Scanf("%d", &b)
//if b > 18 {
// fmt.Print("成年")
//} else if b == 18 {
// fmt.Print("刚成年")
//} else {
// fmt.Print("未成年")
//}
if fmt.Scanf("%d", &b); b > 18 {
fmt.Print("成年")
} else if b == 18 {
fmt.Print("刚成年")
} else {
fmt.Print("未成年")
}
}
2、switch
package main
import (
"fmt"
)
func main() {
fmt.Print("请输入季度: ")
var b int64
fmt.Scanf("%d", &b)
switch b {
case 1:
fmt.Println("第一季度")
case 2:
fmt.Println("第二季度")
case 3:
fmt.Println("第三季度")
case 4:
fmt.Println("第四季度")
default:
fmt.Println("未知季度")
}
}
package main
import (
"fmt"
)
func main() {
fmt.Print("请输入月份: ")
var b int64
fmt.Scanf("%d", &b)
switch {
case b >= 1 && b < 4:
fmt.Println("第一季度")
case b >= 4 && b < 7:
fmt.Println("第二季度")
case b >= 7 && b < 10:
fmt.Println("第三季度")
case b >= 10 && b < 12:
fmt.Println("第四季度")
default:
fmt.Println("未知季度")
}
}
package main
import (
"fmt"
)
func main() {
fmt.Print("请输入月份: ")
var b int64
fmt.Scanf("%d", &b)
switch b {
case 1, 2, 3:
fmt.Println("第一季度")
case 4, 5, 6:
fmt.Println("第二季度")
case 7, 8, 9:
fmt.Println("第三季度")
case 10, 11, 12:
fmt.Println("第四季度")
default:
fmt.Println("未知季度")
}
}
package main
import (
"fmt"
)
func main() {
fmt.Print("请输入月份: ")
var b int64
fmt.Scanf("%d", &b)
switch b {
case 1, 2, 3:
fmt.Println("第一季度")
fmt.Println("第一季度")
// 穿透case
fallthrough
case 4, 5, 6:
fmt.Println("第二季度")
fmt.Println("第二季度")
case 7, 8, 9:
fmt.Println("第三季度")
// 强制结束case
break
fmt.Println("第三季度")
case 10, 11, 12:
fmt.Println("第四季度")
default:
fmt.Println("未知季度")
}
}
7.2、循环语句
1、for
package main
import (
"fmt"
)
func main() {
fmt.Print("请输入数字: ")
var b int
fmt.Scanf("%d", &b)
for a := 1; a <= b; a++ {
fmt.Println(a)
}
}
package main
import (
"fmt"
)
func main() {
fmt.Print("请输入数字: ")
var b int
fmt.Scanf("%d", &b)
//for a := 1; a <= b; a++ {
// fmt.Println(a)
//}
a := 1
// 相当于while循环
for a <= b {
fmt.Println(a)
a++
}
}
// 九九乘法表
package main
import "fmt"
func main() {
for a := 1; a < 10; a++ {
for b := 1; b <= a; b++ {
if b > 0 {
fmt.Print(" ")
}
fmt.Printf("%d*%d=%d", a, b, a*b)
}
fmt.Println()
}
}
// 水仙花数
package main
import "fmt"
func main() {
for a := 100; a < 1000; a++ {
b := a
result := 0
for ; b != 0; b = b / 10 {
c := b % 10
result += c * c * c
}
if result == a {
fmt.Println(a)
}
}
}
// 素数
package main
func main() {
count := 0
for a := 2; a <= 100; a++ {
var b = 2
for ; b < a; b++ {
if a%b == 0 {
break
}
}
if b == a {
println(a)
count++
}
}
println("总数:", count)
}
2、goto
暂不介绍
8、函数
函数也属于复合类型
8.1、基础使用
package main
import "fmt"
func main() {
_m, _n, _result := add(1, 10)
fmt.Println(_m, _n, _result)
}
// 具名返回值可直接return
func add(m, n int) (_m, _n, _result int) {
result := 0
for i := m; i <= n; i++ {
result += i
}
return m, n, result
}
8.2、可变参数
package main
import "fmt"
func main() {
fmt.Println(add1(1, 2, 100))
}
// 只能有一个,且必须是最后一个
func add1(m ...int) ([]int, int) {
result := 0
for _, v := range m {
result += v
}
return m, result
}
8.3、匿名函数
package main
import "fmt"
func main() {
fmt.Println("主函数。。。")
func() {
fmt.Println("匿名函数。。。")
}()
}
package main
import "fmt"
func main() {
fmt.Println("主函数。。。")
var fun = func() {
fmt.Println("匿名函数。。。")
}
fun()
fun()
}
8.4、递归函数
package main
func main() {
println(fibonacci(12))
}
// fibonacci
func fibonacci(n int) (_result int) {
if n == 1 || n == 2 {
return 1
}
return fibonacci(n-1) + fibonacci(n-2)
}
package main
func main() {
println(nn(5))
}
func nn(n int) int {
if n == 1 {
return 1
}
return n * nn(n-1)
}
8.5、回调函数
package main
func main() {
_, _, result := callback(1, 10, add)
print(result)
}
func add(m, n int) (_m, _n, _result int) {
result := 0
for i := m; i <= n; i++ {
result += i
}
return m, n, result
}
func callback(m, n int, fun func(int, int) (int, int, int)) (_m, _n, _result int) {
return fun(m, n)
}
8.6、defer
将指定函数放入任务栈,延迟函数在父级函数return前执行(注意是延迟执行,不是延迟调用)
package main
func main() {
iprint(1)
iprint(2)
defer iprint(3)
iprint(4)
iprint(5)
defer iprint(6) // 1 2 4 5 6 3
}
func iprint(n int) {
println(n)
}
8.7、闭包
package main
import "fmt"
func main() {
result := add(10)
fmt.Println(result()) // 1
fmt.Println(result()) // 2
}
func add(n int) func() int {
result := n
return func() int {
result += 1
return result
}
}
9、指针
9.1、基本使用
package main
import "fmt"
func main() {
// &表取地址,*表取值
a := 10
fmt.Printf("a的值是%d,a的数据类型是%T,a的地址是%p\n", a, a, &a)
p := &a
fmt.Printf("p的地址是%p,p的数据类型是%T,p地址的数据是%d\n", p, p, *p)
p1 := &p
fmt.Printf("p1的地址是%p,p1的数据类型是%T,p1地址的数据是%p\n", p1, p1, *p1)
}
9.2、数组指针/指针数组
package main
import "fmt"
func main() {
a := [3]string{"xumeng03", "xumeng02", "xumeng01"}
b := [3]string{"xumeng03", "xumeng02", "xumeng01"}
c := [3]string{"xumeng03", "xumeng02", "xumeng01"}
fmt.Printf("a的值是%d,a的数据类型是%T,a的地址是%p\n", a, a, &a)
// 数组指针
p := &a
fmt.Printf("p的地址是%p,p的数据类型是%T,p地址的数据是%d\n", p, p, *p)
// 指针数组
var p1 = []*[3]string{&a, &b, &c}
fmt.Printf("p1的地址是%p,p1的数据类型是%T,p1地址的数据是%d\n", p1, p1, p1)
}
9.3、函数指针/指针函数
package main
import "fmt"
func main() {
// 函数指针
fmt.Printf("%p\n", a)
// 指针函数
i := b()
fmt.Printf("%p %v", i, i)
}
func a() {
fmt.Println("a...")
}
func b() *[4]int {
a := [4]int{1, 2, 3, 4}
fmt.Printf("%p\n", &a)
return &a
}
9.4、指针作为参数
package main
func main() {
var n = 1
a(n)
println(n)
b(&n)
println(n)
}
func a(n int) {
n = 10
}
func b(p *int) {
*p = 10
}
10、结构体
结构体属于值类型
10.1、基础使用
package main
import "fmt"
func main() {
// 方法1:声明并初始化Person
var p1 Person = Person{}
p1.name = "xumeng03"
p1.age = 23
p1.sex = true
p1.address = "shanghai"
fmt.Println(p1)
// 方法2:使用字面量初始化Person
var p2 = Person{
"xumeng03", 23, true, "shanghai",
}
fmt.Println(p2)
// 方法3:使用字面量初始化Person部分属性
var p3 = Person{
name: "xumeng03",
}
fmt.Println(p3)
}
type Person struct {
name string
age int
sex bool
address string
}
10.2、结构体指针
package main
import "fmt"
func main() {
var p1 = Person{
"xumeng03", 23, true, "shanghai",
}
fmt.Println(p1)
var pp1 *Person = &p1
// (*pp1).name = "Xumeng03"
pp1.name = "Xumeng03"
fmt.Println(p1, pp1)
var pp2 *Person = new(Person)
pp2 = &p1
// (*pp1).name = "Xumeng03"
pp2.age = 24
fmt.Println(p1, pp2)
}
type Person struct {
name string
age int
sex bool
address string
}
10.3、匿名结构体
package main
import "fmt"
func main() {
// 匿名结构体
var s1 = struct {
name string
age int
}{"xumeng03", 23}
fmt.Println(s1, s1.name)
}
10.4、匿名字段
package main
import "fmt"
func main() {
// 匿名字段(一个类型只能有一个)
var s1 = struct {
string
int
}{"xumeng03", 23}
fmt.Println(s1, s1.string)
}
10.5、结构体嵌套
package main
import "fmt"
func main() {
//var p1 = Person{
// name: "xumeng03",
// age: 23,
// sex: true,
// address: Address{
// name: "shanghai",
// },
//}
var p1 = Person{
"xumeng03",
23,
true,
&Address{
name: "shanghai",
},
}
fmt.Println(p1)
}
type Person struct {
name string
age int
sex bool
//address Address
// 防止值传递
address *Address
}
type Address struct {
name string
}
10.6、方法
package main
import "fmt"
func main() {
//var p1 = Person{
// name: "xumeng03",
// age: 23,
// sex: true,
// address: Address{
// name: "shanghai",
// },
//}
var p1 = Person{
"xumeng03",
23,
true,
}
fmt.Println(p1.hello("bilibili"))
}
type Person struct {
name string
age int
sex bool
}
func (p Person) hello(name string) string {
return p.name + "向 " + name + " 打招呼!"
}
10.7、结构体中的继承
package main
import "fmt"
func main() {
var p1 = Person{
"xumeng03",
23,
true,
}
fmt.Println(p1.hello("bilibili"))
var s1 = Student{
Person{
"xumeng03",
23,
true,
},
10010,
"眼眸流转",
"安阳师范学院",
}
fmt.Println(s1.name, s1.age, s1.hello("bilibili")) // 继承了Person的方法,如果Student中有与Person同名的方法或者属性,则为覆盖。
}
type Person struct {
name string
age int
sex bool
}
type Student struct {
Person
num int
name string
school string
}
func (p Person) hello(name string) string {
return p.name + "向 " + name + " 打招呼!"
}
11、接口
11.1、基础使用
package main
import "fmt"
func main() {
var j = JuniorHighStudent{
name: "xumeng02",
}
study(j, "物理")
var h = HighStudent{
name: "xumeng03",
}
study(h, "化学")
}
type IStudent interface {
study(name string) string
}
type HighStudent struct {
name string
}
type JuniorHighStudent struct {
name string
}
// 接口实现
func (j JuniorHighStudent) study(name string) string {
return j.name + " study " + name
}
// 接口实现
func (j HighStudent) study(name string) string {
return j.name + " study " + name
}
func study(iStudent IStudent, name string) {
fmt.Println(iStudent.study(name))
}
11.2、接口继承
package main
import "fmt"
func main() {
var j = JuniorHighStudent{
name: "xumeng02",
}
study(j, "物理")
var h = HighStudent{
name: "xumeng03",
}
study(h, "化学")
}
type IStudent interface {
study(name string) string
}
// IStudent1 接口继承
type IStudent1 interface {
IStudent
study1(name string) string
}
type HighStudent struct {
name string
}
type JuniorHighStudent struct {
name string
}
// 接口实现
func (j JuniorHighStudent) study(name string) string {
return j.name + " study " + name
}
// 接口实现
func (j HighStudent) study(name string) string {
return j.name + " study " + name
}
func study(iStudent IStudent, name string) {
fmt.Println(iStudent.study(name))
}
11.3、接口断言
package main
import (
"fmt"
"math"
)
func main() {
var t Shape = Triangle{3, 4, 5}
fmt.Println(t.Perimeter(), t.Area())
InterfaceType(&t)
var c Shape = Circle{5}
fmt.Println(c.Perimeter(), c.Area())
InterfaceType(&c)
var s Shape = Square{5}
fmt.Println(s.Perimeter(), s.Area())
InterfaceType(&s)
}
type Shape interface {
Perimeter() float64
Area() float64
}
// Triangle 三角形
type Triangle struct {
a, b, c float64
}
func (t Triangle) Perimeter() float64 {
return t.a + t.b + t.c
}
func (t Triangle) Area() float64 {
var p = t.Perimeter() / 2
return math.Sqrt(p * (p - t.a) * (p - t.b) * (p - t.c))
}
// Circle 圆形
type Circle struct {
r float64
}
func (c Circle) Perimeter() float64 {
return 2 * c.r * math.Pi
}
func (c Circle) Area() float64 {
return math.Pow(c.r, 2) * math.Pi
}
// Square 正方形
type Square struct {
s float64
}
func (s Square) Perimeter() float64 {
return 4 * s.s
}
func (s Square) Area() float64 {
return math.Pow(s.s, 2)
}
// InterfaceType 接口断言
func InterfaceType(shape *Shape) {
// 方法1
//if _, ok := (*shape).(Triangle); ok {
// fmt.Println("三角形")
//} else if _, ok := (*shape).(Circle); ok {
// fmt.Println("圆形")
//} else if _, ok := (*shape).(Square); ok {
// fmt.Println("正方形")
//} else {
// fmt.Println("未知形状")
//}
// 方法2
switch (*shape).(type) {
case Triangle:
fmt.Println("三角形")
case Circle:
fmt.Println("圆形")
case Square:
fmt.Println("正方形")
default:
fmt.Println("未知形状")
}
}
11.4、接口嵌套
package main
func main() {
}
type V1 interface {
v1()
}
type V2 interface {
V1
v2()
}
type V3 interface {
V2
v3()
}
12、自定义类型
package main
import "fmt"
func main() {
var a iint = 100
// var b int = a
fmt.Println(a)
var aa mint = 100
var bb int = aa
fmt.Println(bb)
}
// 自定义类型
type iint int
// 类型别名
type mint = int
13、异常/错误
13.1、基础使用
package main
import (
"fmt"
"os"
)
func main() {
open, err := os.Open("1.txt")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(open.Name(), "open success!")
}
13.2、自定义异常
package main
import (
"fmt"
)
func main() {
err1 := prime(3)
if err1 != nil {
fmt.Println(err1)
return
}
fmt.Println("=====================")
err2 := prime(1)
if err2 != nil {
fmt.Println(err2)
return
}
}
func prime(n int) error {
if n < 2 {
// 方法1:errors.New
//err := errors.New("不合法数字!")
// 方法2:
err := fmt.Errorf("不合法数字!%d", 100)
return err
}
var i int
for i = 2; i < n; i++ {
if n%i == 0 {
break
}
}
if i >= n {
fmt.Println("是素数")
} else {
fmt.Println("不是素数")
}
return nil
}
package main
import (
"fmt"
"strconv"
)
func main() {
b, err := prime(1)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(b)
}
type PrimeError struct {
int
string
}
func (e PrimeError) Error() string {
return strconv.FormatInt(int64(e.int), 10) + "是非法数字!"
}
func prime(n int) (bool, *PrimeError) {
if n < 2 {
return false, &PrimeError{n, "非法数字"}
}
var i int
for i = 2; i < n; i++ {
if n%i == 0 {
break
}
}
if i >= n {
return true, &PrimeError{n, "是素数"}
} else {
return false, &PrimeError{n, "不是素数"}
}
}
13.3、自定义错误(panic/recover)
package main
import "fmt"
func main() {
defer println("start")
fori(20)
defer println("end")
println("bilibili")
}
func fori(n int) {
defer func() {
if a := recover(); a != nil {
fmt.Println(a, "恢复运行")
}
}()
defer println("fori...start")
for i := 0; i < n; i++ {
fmt.Println(i)
if i == 10 {
// 恐慌,只有panic前所有defer都被执行后,panic才会被传递到调用处
panic("遇到了10!")
}
}
defer println("fori...end")
}
14、并发编程
并发:同时处理多个任务(单处理器,也就是说一个时间点只做一件事,但是多个任务交替)
并行:同时执行多个任务(多处理器,也就是说一个时间点做多件事,多个任务同时进行)
不要使用共享内存的方式通信,而要以通信的方式共享内存!
14.1、基本使用
协程执行的函数一般没有返回值,即是有也会被舍弃
package main
import "fmt"
func main() {
go iPrint("\tgoroutine1")
go iPrint("\tgoroutine2")
// 默认情况下主goroutine并不会等待其他goroutine执行完毕才结束
// 因此此处goroutine1和goroutine2有可能未执行完成
iPrint("主goroutine")
}
func iPrint(str string) {
for i := 0; i < 50; i++ {
fmt.Println(str, "打印", i)
}
}
14.2、无缓冲通道
package main
import (
"fmt"
)
// 无缓冲通道,读取和发送都会阻塞通道
var channel = make(chan string)
func push(str string) {
fmt.Println("开始发送数据")
channel <- str
fmt.Println("发送数据完成")
}
func pop() {
fmt.Println("开始读取数据")
fmt.Println(<-channel)
fmt.Println("读取数据完成")
}
func main() {
// 读取阻塞
//go push("xumeng03")
//pop()
// 发送阻塞
go pop()
go pop()
go pop()
push("xumeng01")
push("xumeng02")
push("xumeng03")
}
package main
import (
"fmt"
"strconv"
"time"
)
// 无缓冲通道,读取和发送都会阻塞通道,容量为0
var channel = make(chan string)
func main() {
go func() {
for i := 0; i < 10; i++ {
//time.Sleep(time.Second)
channel <- "xumeng" + strconv.Itoa(i)
fmt.Println("数据已压入通道", time.Now().Format("2006-01-02 15:04:05"))
}
// 关闭通道
close(channel)
}()
for s := range channel {
time.Sleep(time.Second)
fmt.Println(s, time.Now().Format("2006-01-02 15:04:05"))
}
}
14.3、缓冲通道
package main
import (
"fmt"
"strconv"
"time"
)
// 缓冲通道,发送数据时若缓冲区已满则阻塞,接收数据若缓冲区为空则阻塞
var channel = make(chan string, 5)
func main() {
go func() {
for i := 0; i < 100; i++ {
channel <- "xumeng" + strconv.Itoa(i)
fmt.Println("数据已压入通道", time.Now().Format("2006-01-02 15:04:05"))
}
// 关闭通道
close(channel)
}()
for s := range channel {
time.Sleep(time.Second)
fmt.Println(s, time.Now().Format("2006-01-02 15:04:05"))
}
}
14.4、定向通道
主要用于传参数参数类型,保护数据
package main
// 定向通道
var rchannel = make(<-chan string)
var wchannel = make(chan<- string)
func main() {
// 不可写入
//rchannel <- "111"
// 不可读取
//<-wchannel
}
package main
import "fmt"
func main() {
var channel = make(chan int)
go func() {
for i := 0; i < 100; i++ {
push(channel, i)
}
close(channel)
}()
for n := range channel {
fmt.Println(n)
}
}
func push(channel chan<- int, n int) {
channel <- n
}
func pop(channel <-chan int) {
fmt.Println(<-channel)
}
14.5、select
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
var c1 = make(chan int)
var c2 = make(chan int)
go func() {
rand.NewSource(time.Now().UnixNano())
time.Sleep(10 * time.Second)
c1 <- rand.Intn(100)
}()
go func() {
rand.NewSource(time.Now().UnixNano())
time.Sleep(10 * time.Second)
c2 <- rand.Intn(100)
}()
select {
case n := <-c1:
fmt.Println("c1", n)
case n := <-c2:
fmt.Println("c2", n)
case <-time.After(5 * time.Second):
fmt.Println("timeout!")
}
}
15、内置包
标准库 - Go 包:https://pkg.go.dev/std
15.1、fmt
1、Print/Println/Sprint/Sprintln
func Print(a ...any) (n int, err error)
打印数据,不换行
package main
import "fmt"
func main() {
fmt.Print("hello world")
s1 := fmt.Sprint("hello world")
fmt.Print(s1)
fmt.Println("hello world")
s2 := fmt.Sprintln("hello world")
fmt.Print(s2)
}
2、Printf/Sprintf
func Printf(format string, a ...any) (n int, err error)
打印格式化数据
package main
import "fmt"
func main() {
a := 11
fmt.Printf("类型: %T,值: %d,二进制值 %b,八进制值 %o,十进制值 %d,十六进制值 %x,十六进制值 %X,地址 %p\n", a, a, a, a, a, a, a, &a)
a1 := fmt.Sprintf("类型: %T,值: %d,二进制值 %b,八进制值 %o,十进制值 %d,十六进制值 %x,十六进制值 %X,地址 %p", a, a, a, a, a, a, a, &a)
fmt.Println(a1)
s := "hello world"
fmt.Printf("类型: %T,值: %s,地址 %p\n", s, s, &s)
s1 := fmt.Sprintf("类型: %T,值: %s,地址 %p", s, s, &s)
fmt.Println(s1)
}
15.2、strings
字符串相关函数
1、Compare
func Compare(a, b string) int
按字典顺序比较两个字符串, 如果 a == b,则结果为 0;如果 a < b,则结果为 -1;如果 a > b,则结果为 +1。
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Compare("a", "b")) // -1
fmt.Println(strings.Compare("a", "a")) // 0
fmt.Println(strings.Compare("b", "a")) // 1
}
2、Contains/ContainsAny
func Contains(s, substr string) bool
判断包含 substr 是否在 s 内
func ContainsAny(s, chars string) bool
判断s中是否包含chars中的任意一个字符
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Contains("seafood", "foo")) // true
fmt.Println(strings.Contains("seafood", "bar")) // false
fmt.Println(strings.Contains("seafood", "")) // true
fmt.Println(strings.Contains("", "")) // true
fmt.Println(strings.ContainsAny("team", "i")) // false
fmt.Println(strings.ContainsAny("fail", "ui")) // true
fmt.Println(strings.ContainsAny("ure", "ui")) // true
fmt.Println(strings.ContainsAny("failure", "ui")) // true
// chars是空字符串,因此没有任何字符可以在其中进行匹配。所以无论s是什么字符串,都不会在空字符串中存在匹配的字符
fmt.Println(strings.ContainsAny("foo", "")) // false
fmt.Println(strings.ContainsAny("", "")) // false
}
3、Count
func Count(s, substr string) int
判断s中是否包含chars中的任意一个字符
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Count("cheese", "e")) // 3
// 如果 substr 为空字符串,则 Count 返回 1 + len(s)
fmt.Println(strings.Count("five", "")) // 5
}
4、Cut/CutPrefix/CutSuffix
func Cut(s, sep string) (before, after string, found bool)
在s中根据sep切割字符串并返回前、后、是否查询到切割字符
package main
import (
"fmt"
"strings"
)
func main() {
show := func(s, sep string) {
before, after, found := strings.Cut(s, sep)
fmt.Printf("%q, %q, %v\n", before, after, found)
}
show("Gopher", "Go") // "", "pher", true
show("Gopher", "ph") // "Go", "er", true
show("Gopher", "er") // "Goph", "", true
// 如未找到,after=s
show("Gopher", "Badger") // "Gopher", "", false
}
func CutPrefix(s, prefix string) (after string, found bool)
判断s是否以sep开头,如是则返回切割后结果,如不是则返回s
package main
import (
"fmt"
"strings"
)
func main() {
show := func(s, sep string) {
after, found := strings.CutPrefix(s, sep)
fmt.Printf("CutPrefix(%q, %q) = %q, %v\n", s, sep, after, found)
}
show("Gopher", "Go") // "pher", true
show("Gopher", "ph") // "Gopher", false
}
func CutSuffix(s, suffix string) (before string, found bool)
判断s是否以s结尾,如是则返回切割后结果,如不是则返回s
package main
import (
"fmt"
"strings"
)
func main() {
show := func(s, sep string) {
before, found := strings.CutSuffix(s, sep)
fmt.Printf("CutSuffix(%q, %q) = %q, %v\n", s, sep, before, found)
}
show("Gopher", "Go") // "Gopher", false
show("Gopher", "er") // "Goph", true
}
5、EqualFold
func EqualFold(s, t string) bool
判断s和t是否相等(忽略大小写)
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.EqualFold("Go", "go"))
fmt.Println(strings.EqualFold("AB", "ab")) // true
fmt.Println(strings.EqualFold("ß", "ss")) // false
}
6、Fields
func Fields(s string) []string
根据空格分隔s
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Printf("Fields are: %q", strings.Fields(" foo bar baz ")) // ["foo" "bar" "baz"]
}
7、HasPrefix/HasSuffix
func HasPrefix(s, prefix string) bool
判断s是否以prefix 开头
func HasSuffix(s, suffix string) bool
判断s是否以suffix结尾
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.HasPrefix("Gopher", "Go")) // true
fmt.Println(strings.HasPrefix("Gopher", "C")) // false
fmt.Println(strings.HasPrefix("Gopher", "")) // true
fmt.Println(strings.HasSuffix("Amigo", "go")) // true
fmt.Println(strings.HasSuffix("Amigo", "O")) // false
fmt.Println(strings.HasSuffix("Amigo", "Ami")) // false
fmt.Println(strings.HasSuffix("Amigo", "")) //true
}
8、Index/LastIndex
func Index(s, substr string) int
返回 s 中第一个 substr 的索引,如果不存在,则返回 -1
func LastIndex(s, substr string) int
返回 s 中最后一个 substr 实例的索引,如果 s 中不存在 substr,则返回 -1
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Index("chicken", "ken")) // 4
// 未检索到,则返回-1
fmt.Println(strings.Index("chicken", "dmr")) // -1
fmt.Println(strings.LastIndex("go gopher", "go")) // 3
fmt.Println(strings.LastIndex("go gopher", "rodent")) // -1
}
9、Join
func Join(elems []string, sep string) string
以sep作为分隔符,拼接string数组
package main
import (
"fmt"
"strings"
)
func main() {
s := []string{"foo", "bar", "baz"}
fmt.Println(strings.Join(s, ",")) // foo,bar,baz
}
10、Repeat
func Repeat(s string, count int) string
返回一个重复count次的s字符串
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println("ba" + strings.Repeat("na", 2)) // banana
}
11、Replace/ReplaceAll
func Replace(s, old, new string, n int) string
在s中使用new替换old,最多替换n次
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Replace("oink oink oink", "k", "ky", 2))
// n<0 则表示全局替换
fmt.Println(strings.Replace("oink oink oink", "oink", "moo", -1))
}
func ReplaceAll(s, old, new string) string
在s中使用new替换所有old
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.ReplaceAll("oink oink oink", "oink", "moo"))
}
12、Split/SplitAfter
func Split(s, sep string) []string
使用sep分割s,返回string数组
func SplitAfter(s, sep string) []string
使用sep分割s,返回string数组(保留分隔符)
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Printf("%q\n", strings.Split("a,b,c", ","))
fmt.Printf("%q\n", strings.SplitAfter("a,b,c", ","))
}
13、ToUpper/ToLower
func ToUpper(s string) string
将s转为大写
func ToLower(s string) string
将s转为小写
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.ToUpper("Gopher"))
fmt.Println(strings.ToLower("Gopher"))
}
14、Trim/TrimLeft/TrimRight/TrimSpace
func Trim(s, cutset string) string
清除s中cutset中存在的字符
func TrimLeft(s, cutset string) string
清除s左侧所有中cutset中存在的字符,直至第一个非cutset中存在的字符
func TrimRight(s, cutset string) string
清除s右侧所有中cutset中存在的字符,直至第一个非cutset中存在的字符
func TrimSpace(s string) string
清楚s中空格、换行、制表符
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Print(strings.Trim("¡¡¡Hello, Gophers!!!", "!¡"))
fmt.Print(strings.TrimLeft("¡¡¡Hello, Gophers!!!", "!¡"))
fmt.Print(strings.TrimRight("¡¡¡Hello, Gophers!!!", "!¡"))
fmt.Println(strings.TrimSpace(" \t\n Hello, Gophers \n\t\r\n"))
}
15.3、strconv
基本类型的转换
1、Atoi/Itoa
func Atoi(s string) (int, error)
将字符串转为int
func Itoa(i int) string
将int转为字符串
package main
import (
"fmt"
"strconv"
)
func main() {
var a = 1
fmt.Println(strconv.Itoa(a))
var b = "10"
fmt.Println(strconv.Atoi(b))
}
2、FormatInt/FormatFloat/FormatBool
func FormatInt(i int64, base int) string
将int转为string
func FormatFloat(f float64, fmt byte, prec, bitSize int) string
将float转为string
func FormatBool(b bool) string
将bool转为string
package main
import (
"fmt"
"strconv"
)
func main() {
var a int64 = 1
fmt.Println(strconv.FormatInt(a, 10))
var b = 3.14
fmt.Println(strconv.FormatFloat(b, 'g', -1, 64))
var c = true
fmt.Println(strconv.FormatBool(c))
}
3、ParseInt/ParseFloat/ParseBool
func ParseInt(s string, base int, bitSize int) (i int64, err error)
将字符串解析为int
func ParseFloat(s string, bitSize int) (float64, error)
将字符串解析为float
func ParseBool(str string) (bool, error)
将字符串解析为bool
package main
import (
"fmt"
"strconv"
)
func main() {
var a = "1"
fmt.Println(strconv.ParseInt(a, 10, 64))
var b = "3.14"
fmt.Println(strconv.ParseFloat(b, 10))
var c = "true"
fmt.Println(strconv.ParseBool(c))
}
15.4、time
1、Now
func Now() Time
获取当前时间
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Now())
}
2、Date
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time
获取指定的时间
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Date(2023, 10, 30, 22, 22, 22, 0, time.UTC))
fmt.Println(time.Date(2023, 10, 30, 22, 22, 22, 0, time.Local))
}
3、Format
func (t Time) Format(layout string) string
格式化时间
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
}
4、Parse
func Parse(layout, value string) (Time, error)
将字符串解析为时间
package main
import (
"fmt"
"time"
)
func main() {
var str = "2023-10-30 10:00:00"
parse, err := time.Parse("2006-01-02 15:04:05", str)
if err != nil {
fmt.Println(err)
}
fmt.Println(parse)
}
5、Date/Clock
func (t Time) Date() (year int, month Month, day int)
获取时间的年月日
func (t Time) Clock() (hour, min, sec int)
获取时间的时分秒
package main
import (
"fmt"
"time"
)
func main() {
var t = time.Now()
year, month, day := t.Date()
hour, min, sec := t.Clock()
fmt.Println(year, month, day)
fmt.Println(hour, min, sec)
}
6、Year/Month/Day/Hour/Minute/Second/Nanosecond/YearDay/Weekday
func (t Time) Year() int
获取时间的年份
func (t Time) Month() Month
获取时间的月份
func (t Time) Day() int
获取时间的日期
func (t Time) Hour() int
获取时间的小时
func (t Time) Minute() int
获取时间的分钟
func (t Time) Second() int
获取时间的秒钟
func (t Time) Nanosecond() int
获取时间的纳秒
func (t Time) YearDay() int
获取时间的在年份中的天数
func (t Time) Weekday() Weekday
获取时间是周几
package main
import (
"fmt"
"time"
)
func main() {
var t = time.Now()
fmt.Println("年份", t.Year())
fmt.Println("月份", t.Month())
fmt.Println("日期", t.Day())
fmt.Println("时", t.Hour())
fmt.Println("分", t.Minute())
fmt.Println("秒", t.Second())
fmt.Println("纳秒", t.Nanosecond())
fmt.Println("此年份第", t.YearDay(), "天")
fmt.Println("当天是", t.Weekday())
}
7、Unix/UnixNano
func (t Time) Unix() int64
获取时间距1970-1-1 00:00:00的时间差值(单位:秒)
func (t Time) UnixNano() int64
获取时间距1970-1-1 00:00:00的时间差值(单位:纳秒)
package main
import (
"fmt"
"time"
)
func main() {
var t = time.Now()
fmt.Println(t.Unix())
fmt.Println(t.UnixNano())
}
8、Add/AddDate
func (t Time) Add(d Duration) Time
在当前时间基础添加/减少时间
func (t Time) AddDate(years int, months int, days int) Time
在当前时间基础添加/减少日期
package main
import (
"fmt"
"time"
)
func main() {
var t = time.Now()
fmt.Println(t)
fmt.Println(t.Add(24 * time.Hour))
fmt.Println(t.AddDate(0, 1, 0))
fmt.Println(t.Add(-24 * time.Hour))
fmt.Println(t.AddDate(0, -1, 0))
}
9、Sleep
func Sleep(d Duration)
沉睡指定时间
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Now())
time.Sleep(3 * time.Second)
fmt.Println(time.Now())
}
10、NewTimer
func NewTimer(d Duration) *Timer
创建一个定时器,到达指定时间激活一次,timer.C为内部的无缓冲通道
package main
import (
"fmt"
"time"
)
func main() {
var timer = time.NewTimer(5 * time.Second)
//go func() {
// <-timer.C
// fmt.Println("这是5秒后啦")
//}()
//time.Sleep(10 * time.Second)
func() {
<-timer.C
fmt.Println("这是5秒后啦")
}()
}
package main
import (
"fmt"
"time"
)
func main() {
var timer = time.NewTimer(5 * time.Second)
go func() {
<-timer.C
fmt.Println("这是5秒后啦")
}()
time.Sleep(time.Second)
// 取消定时器
stop := timer.Stop()
if stop {
fmt.Println("计时器已停止!")
}
time.Sleep(10 * time.Second)
}
11、NewTicker
间隔指定时间激活一次
func NewTicker(d Duration) *Ticker
创建一个心跳,间隔指定时间激活一次,ticker.C为内部的无缓冲通道
package main
import (
"fmt"
"time"
)
func main() {
var ticker = time.NewTicker(2 * time.Second)
defer ticker.Stop()
var flag = make(chan bool)
go func() {
time.Sleep(10 * time.Second)
flag <- true
}()
for {
select {
case <-flag:
fmt.Println("结束程序!")
return
case <-ticker.C:
fmt.Println("定时器激活!")
}
}
}
15.5、path
1、Join
func Join(elem ...string) string
拼接路径
package main
import (
"fmt"
"path"
)
func main() {
fmt.Println(path.Join("gostudy", "go.mod"))
}
2、Split
func Split(path string) (dir, file string)
分割路径
package main
import (
"fmt"
"path"
)
func main() {
var p = "/root/GolandProjects/gostudy/go.mod"
fmt.Println(path.Split(p))
}
3、Dir/Base/
func Dir(path string) string
获取路径的目录部分
func Base(path string) string
获取路径的文件部分
func Ext(path string) string
获取路径的文件扩展名部分
package main
import (
"fmt"
"path"
)
func main() {
var p = "/root/GolandProjects/gostudy/go.mod"
fmt.Println(path.Dir(p))
fmt.Println(path.Base(p))
fmt.Println(path.Ext(p))
}
15.6、os
1、Mkdir/MkdirAll
func Mkdir(name string, perm FileMode) error
创建目录,如父目录不存在则报错
func MkdirAll(path string, perm FileMode) error
创建目录,如父目录不存在则创建
// 注意这里使用的是windows!
package main
import (
"fmt"
"os"
)
func main() {
err := os.Mkdir("aaa", os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("make dir success!")
err1 := os.MkdirAll("aaa\\bbb\\cc", os.ModePerm)
if err1 != nil {
fmt.Println(err1)
return
}
fmt.Println("make dir success!")
}
2、ReadDir
func ReadDir(name string) ([]DirEntry, error)
读取文件夹
package main
import (
"fmt"
"os"
)
func main() {
dir, err := os.ReadDir("/Users/xumeng03/Downloads")
if err != nil {
fmt.Println(err)
return
}
for _, d := range dir {
if d.IsDir() {
fmt.Println(d.Name())
}
}
}
3、Create
func Create(name string) (*File, error)
创建文件,如存在则会清空文件
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.Create("a.txt")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("create file success!", file)
}
4、Stat
func Stat(name string) (FileInfo, error)
获取文件信息
package main
import (
"fmt"
"os"
)
func main() {
stat, err := os.Stat("go.mod")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("文件名称:", stat.Name())
fmt.Println("文件大小:", stat.Size())
fmt.Println("文件模式:", stat.Mode())
fmt.Println("文件修改时间:", stat.ModTime())
fmt.Println("文件是否未目录:", stat.IsDir())
}
5、Open/OpenFile
func Open(name string) (*File, error)
以O_RDONLY打开文件
func OpenFile(name string, flag int, perm FileMode) (*File, error)
以指定模式打开文件
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.Open("a.txt")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("open file success!", file)
err = file.Close()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("close file success!", file)
// os.O_RDONLY // 只读
// os.O_WRONLY // 只写
// os.O_RDWR // 读写
// os.O_APPEND // 往文件中添建(Append)
// os.O_CREATE // 如果文件不存在则先创建
// os.O_TRUNC // 文件打开时裁剪文件
// os.O_EXCL // 和O_CREATE一起使用,文件不能存在
// os.O_SYNC // 以同步I/O的方式打开
file, err = os.OpenFile("a.txt", os.O_WRONLY, os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("open file success!", file)
err = file.Close()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("close file success!", file)
}
6、Remove/RemoveAll
func Remove(name string) error
移除文件,若为目录且目录下有文件,返回错误
package main
import (
"fmt"
"os"
)
func main() {
err := os.Remove("a.txt")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("remove file success!")
}
func RemoveAll(path string) error
强制移除文件,忽略目录下是否有文件,慎用!
package main
import (
"fmt"
"os"
)
func main() {
err1 := os.MkdirAll("aaa\\bbb\\cc", os.ModePerm)
if err1 != nil {
fmt.Println(err1)
return
}
fmt.Println("make dir success!")
file, err := os.Create("aaa\\bbb\\cc\\a.txt")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("create file success!", file)
err1 = file.Close()
if err1 != nil {
fmt.Println(err1)
return
}
err = os.RemoveAll("aaa\\bbb")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("remove file success!")
}
7、Rename
func Rename(oldpath, newpath string) error
重命名/移动文件
package main
import (
"fmt"
"os"
)
func main() {
err := os.Mkdir("aaa", 0777)
if err != nil {
fmt.Println(err)
return
}
_, err = os.Create("a.txt")
if err != nil {
fmt.Println(err)
return
}
err = os.Rename("a.txt", "aaa/aaa.txt")
if err != nil {
fmt.Println(err)
return
}
}
8、Chmod
func Chmod(name string, mode FileMode) error
修改文件权限
package main
import (
"fmt"
"os"
)
func main() {
_, err := os.Create("a.txt")
if err != nil {
fmt.Println(err)
return
}
err = os.Chmod("a.txt", 0777)
if err != nil {
fmt.Println(err)
return
}
}
func Chown(name string, uid, gid int) error
修改文件所有者
package main
import (
"fmt"
"os"
)
func main() {
_, err := os.Create("a.txt")
if err != nil {
fmt.Println(err)
return
}
// os.Getuid():用户ID
// os.Getgid():组ID
fmt.Println(os.Getuid(), os.Getgid())
err = os.Chown("a.txt", os.Getuid(), os.Getgid())
if err != nil {
fmt.Println(err)
return
}
}
9、Read/ReadFile
func (f *File) Read(b []byte) (n int, err error)
读取指定字节,到结尾读取数n=0,err=io.EOF
package main
import (
"fmt"
"io"
"os"
)
func main() {
file, err := os.Open("a.txt")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("open success!", file)
defer file.Close()
for {
var buffer = make([]byte, 5, 5)
n, err := file.Read(buffer)
if err == io.EOF {
break
}
fmt.Println(string(buffer[:n]))
}
fmt.Println("read end")
}
func ReadFile(name string) ([]byte, error)
读取整个文件内容,只适合小文件!
package main
import (
"fmt"
"os"
)
func main() {
// ioutil.ReadFile
file, err := os.ReadFile("a.txt")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(file))
}
10、Write/WriteString
func (f *File) Write(b []byte) (n int, err error)
写入byte数组到文件
package main
import (
"fmt"
"os"
)
func main() {
// 从开头开始写
//file, err := os.OpenFile("a.txt", os.O_RDWR, os.ModePerm)
// 追加内容
file, err := os.OpenFile("a.txt", os.O_RDWR|os.O_APPEND, os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
var b = []byte("hello world!")
n, err := file.Write(b)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(n)
}
func (f *File) WriteString(s string) (n int, err error)
写入字符串到文件
package main
import (
"fmt"
"os"
)
func main() {
// 从开头开始写
//file, err := os.OpenFile("a.txt", os.O_RDWR, os.ModePerm)
// 追加内容
file, err := os.OpenFile("a.txt", os.O_RDWR|os.O_APPEND, os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
n, err := file.WriteString("hello world!!!")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(n)
}
11、Seek
func (f *File) Seek(offset int64, whence int) (ret int64, err error)
设置光标位置
package main
import (
"fmt"
"io"
"os"
)
func main() {
file, err := os.Create("a.txt")
if err != nil {
fmt.Println(err)
return
}
n, err := file.WriteString("hello world!")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(n)
err = file.Close()
if err != nil {
fmt.Println(err)
return
}
file, err = os.OpenFile("a.txt", os.O_RDWR, os.ModePerm)
// io.SeekStart:文件开头
// io.SeekCurrent:当前位置
// io.SeekEnd:文件结尾
file.Seek(0, io.SeekCurrent)
n, err = file.WriteString("I'm xumeng03!")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(n)
}
12、Truncate
func Truncate(name string, size int64) error
裁剪文件
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.OpenFile("a.txt", os.O_RDWR, os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
err = file.Truncate(8)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("truncate file success!")
}
13、案例:复制文件
package main
import (
"fmt"
"io"
"os"
)
func main() {
originfile, err := os.Open("a.txt")
if err != nil {
fmt.Println(err)
return
}
defer originfile.Close()
newfile, err1 := os.Create("b.txt")
if err1 != nil {
fmt.Println(err1)
return
}
defer newfile.Close()
for {
var b = make([]byte, 1024)
n, err := originfile.Read(b)
if err != nil && err != io.EOF {
fmt.Println(err)
return
}
fmt.Println("read byte:", n)
write, err1 := newfile.Write(b[:n])
if err1 != nil {
fmt.Println(err)
return
}
fmt.Println("write byte:", write)
if err == io.EOF {
break
}
}
fmt.Println("copy success!")
}
15.7、io
1、Copy
func Copy(dst Writer, src Reader) (written int64, err error)
复制文件
package main
import (
"fmt"
"io"
"os"
)
func main() {
originfile, err := os.Open("a.txt")
if err != nil {
fmt.Println(err)
return
}
defer originfile.Close()
newfile, err := os.Create("b.txt")
if err != nil {
fmt.Println(err)
return
}
defer newfile.Close()
written, err := io.Copy(newfile, originfile)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(written)
}
15.8、bufio
1、ReadBytes/ReadString
func (b *Reader) ReadBytes(delim byte) ([]byte, error)
逐行读取(bufio包下)
func (b *Reader) ReadString(delim byte) (string, error)
逐行读取(bufio包下)
package main
import (
"bufio"
"fmt"
"io"
"os"
"strings"
)
func main() {
file, err := os.Open("a.txt")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
//reader := bufio.NewReader(file)
//for {
// bytes, err := reader.ReadBytes('\n')
// if err != nil && err != io.EOF {
// fmt.Println(err)
// return
// }
// fmt.Println(strings.TrimSpace(string(bytes)))
// if err == io.EOF {
// break
// }
//}
reader := bufio.NewReaderSize(file, 1024)
for {
str, err := reader.ReadString('\n')
if err != nil && err != io.EOF {
fmt.Println(err)
return
}
fmt.Println(strings.TrimSpace(str))
if err == io.EOF {
break
}
}
}
2、Write/WriteString
func (b *Writer) Write(p []byte) (nn int, err error)
向文件写入byte数组
func (b *Writer) WriteString(s string) (int, error)
向文件写入字符串
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file, err := os.OpenFile("a.txt", os.O_RDWR, os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
//writer := bufio.NewWriter(file)
//nn, err := writer.Write([]byte("hello world!"))
//if err != nil {
// fmt.Println(err)
// return
//}
//fmt.Println(nn)
writer := bufio.NewWriterSize(file, 1024)
nn, err := writer.WriteString("hello world!!!")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(nn)
writer.Flush()
}
15.9、ioutil
从Go 1.16版本开始,ioutil包中的一些函数已被标记为不推荐使用,因为这些函数在处理大文件时可能会导致内存泄漏或性能问题。
15.10、runtime
1、GOROOT/GOOS/NumCPU/GOMAXPROCS
func GOROOT() string
获取GOROOT路径
func NumCPU() int
获取内核数
func GOMAXPROCS(n int) int
设置go运行时最大可用CPU数
package main
import (
"fmt"
"runtime"
)
func main() {
// 获取GOROOT路径
fmt.Println(runtime.GOROOT())
// 获取系统
fmt.Println(runtime.GOOS)
// 获取内核数
fmt.Println(runtime.NumCPU())
}
func init() {
// 设置go运行时最大可用CPU数
runtime.GOMAXPROCS(runtime.NumCPU())
}
2、Gosched/Goexit
func Gosched()
主动让出执行权
package main
import (
"fmt"
"runtime"
)
func main() {
go func() {
for i := 0; i < 1000; i++ {
fmt.Println("\tgoroutine1:", i)
}
}()
for i := 0; i < 1000; i++ {
if i == 100 {
runtime.Gosched()
}
fmt.Println("goroutine0:", i)
}
}
func Goexit()
结束协程(如有defer函数仍会执行)
package main
import (
"fmt"
"runtime"
)
func main() {
go func() {
for i := 0; i < 1000; i++ {
fmt.Println("\tgoroutine1:", i)
if i == 100 {
runtime.Goexit()
}
}
}()
for i := 0; i < 1000; i++ {
fmt.Println("goroutine0:", i)
}
}
15.11、sync
1、Add/Wait/Done
func (wg *WaitGroup) Add(delta int)
向同步等待组中添加正增量(需要在调用前增加计数)
func (wg *WaitGroup) Done()
向同步等待组中添加负增量
func (wg *WaitGroup) Wait()
等待同步等待组的计数器归零
package main
import (
"fmt"
"sync"
)
var waits = sync.WaitGroup{}
func main() {
waits.Add(1)
go iPrint("\tgoroutine1")
waits.Add(1)
go iPrint("\tgoroutine2")
iPrint("主goroutine")
waits.Wait()
fmt.Println("全部执行完成!")
}
func iPrint(str string) {
for i := 0; i <= 50; i++ {
fmt.Println(str, "打印", i)
}
waits.Done()
}
2、Lock/Unlock
互斥锁:同一时间只有一个协程访问资源
当一个goroutine需要访问共享资源时,它会先调用Mutex的Lock方法来获取锁,如果锁已经被其他goroutine获取,则当前goroutine会被阻塞,直到锁被释放。因此,Mutex并不需要指定对谁加锁,它只需要保证同一时间只有一个goroutine可以获取锁即可
func (m *Mutex) Lock()
获取锁
func (m *Mutex) Unlock()
释放锁
package main
import (
"fmt"
"sync"
"time"
)
var l = sync.Mutex{}
var ticket = 10
func main() {
go iPrint("\tgoroutine1")
go iPrint("\tgoroutine2")
iPrint("主goroutine")
}
func iPrint(str string) {
for i := 0; i <= 10; i++ {
l.Lock()
if ticket > 0 {
time.Sleep(time.Second)
fmt.Println(str, "买出票:", ticket)
ticket--
l.Unlock()
} else {
l.Unlock()
break
}
}
}
3、RLock/RUnlock/Lock/Unlock
读写锁:读的时候随便读,写的时候只能等
package main
import (
"fmt"
"sync"
"time"
)
var l = sync.RWMutex{}
var waits = sync.WaitGroup{}
func main() {
// 多个读操作可以同时进行
//waits.Add(1)
//go read("1")
//waits.Add(1)
//go read("2")
//waits.Add(1)
//go read("3")
//waits.Wait()
//fmt.Println("读取完成")
// 写操作同一时间点只能有一个在进行
//waits.Add(1)
//go write("1")
//waits.Add(1)
//go write("2")
//waits.Add(1)
//go write("3")
//waits.Wait()
//fmt.Println("写入完成")
// 读操作可以穿插,但是写操作不可被打断
waits.Add(1)
go read("1")
waits.Add(1)
go write("2")
waits.Add(1)
go read("3")
waits.Add(1)
go read("4")
waits.Wait()
fmt.Println("写入完成")
}
func read(str string) {
l.RLock()
fmt.Println(str, "开始读操作。。。")
time.Sleep(time.Second)
fmt.Println(str, "假装是一个读操作。。。")
fmt.Println(str, "结束读操作。。。")
l.RUnlock()
waits.Done()
}
func write(str string) {
l.Lock()
fmt.Println(str, "开始写操作。。。")
time.Sleep(5 * time.Second)
fmt.Println(str, "假装是一个写操作。。。")
fmt.Println(str, "结束写操作。。。")
l.Unlock()
waits.Done()
}
16、第三方包
Go Mod:Go语言包管理工具
// 模块名称
module gostudy
// go最低版本
go 1.20
// 依赖
require (
github.com/bytedance/sonic v1.10.2 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.15.5 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/arch v0.5.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
16.1、开启Go Mod
# 启用Go模块支持
go env -w GO111MODULE=on
# 配置Go模块代理GOPROXY
https://mirrors.aliyun.com/goproxy
16.2、Go Mod命令
# 初始化go.mod
go mod init 包名
# 下载包
go get -u github.com/gin-gonic/gin
# 清理未使用依赖包
go mod tidy
# 下载依赖
go mod download
# 更新包
go get -u
# 将依赖下载到项目中
go mod vendor
17、自定义包
- 只能有一个main包作为程序入口
- 一个包可以包含多个Go源文件,但是它们必须在同一个目录下,并且属于同一个包(一般与文件夹名保持一致)
- 以大写字母开头的标识符是可导出的,可以被其他包引用,以小写字母开头的标识符是私有的,只能在当前包内使用
- 包可以有任意个init函数(没有参数,没有返回值),当包被导入时会先执行init函数
- init函数调用顺序是同一个文件中按上下顺序,同一包按照文件首字母排序,不同包中按照导入顺序
- import时用
_
导入包,并不使用该包中的任何函数、变量、类型,只会执行包中的init函数
17.1、基础使用
// 自定义包
package string
import "fmt"
func Count(arr []int) int {
return len(arr)
}
func count(arr []int) int {
return len(arr)
}
func init() {
fmt.Println("string init......")
}
使用自定义包
package main
// 导入包
import (
"fmt"
"golang/utils/string"
)
func main() {
var arr = []int{1, 2, 3, 4}
fmt.Println(string.Count(arr))
}
17.2、省略包名
package main
import (
"fmt"
// 别名
. "golang/utils/string"
)
func main() {
var arr = []int{1, 2, 3, 4}
fmt.Println(Count(arr))
}
17.3、包起别名
package main
import (
"fmt"
// 别名
str "golang/utils/string"
)
func main() {
var arr = []int{1, 2, 3, 4}
fmt.Println(str.Count(arr))
}
17.4、_导入
package main
import (
"fmt"
// 别名
_ "golang/utils/string"
)
func main() {
fmt.Println("main......")
}
17.5、发布自己的包
待补。。。
18、反射
18.1、基本使用
package main
import (
"fmt"
"reflect"
)
func main() {
var f = 3.1415926
fmt.Println("type:", reflect.TypeOf(f), "value:", reflect.ValueOf(f))
value := reflect.ValueOf(f)
fmt.Println("type:", value.Kind())
fmt.Println("value:", value.Float())
}
18.2、获取/设置对象信息
package main
import (
"fmt"
"reflect"
)
func main() {
var person = Person{"xumeng03", 23}
get(person)
set(&person)
fmt.Println(person)
}
// 反射在设置结构体类型的属性时,只能设置被导出的属性!!!
type Person struct {
Name string
Age int
}
// 反射在获取结构体类型的方法时,只会返回被导出的方法!!!
func (p Person) Hello(str string) {
fmt.Println(p.Name, ": hello", str, "!")
}
func get(o interface{}) {
t := reflect.TypeOf(o)
fmt.Println(t.Name(), t.Kind())
v := reflect.ValueOf(o)
fmt.Println(v)
// 属性
fmt.Println("属性个数", t.NumField())
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
fmt.Println("属性名:", field.Name, "属性类型:", field.Type, "属性值:", value)
}
// 方法
fmt.Println("方法个数", t.NumMethod())
for i := 0; i < t.NumMethod(); i++ {
method := t.Method(i)
fmt.Println("方法名:", method.Name, "方法类型:", method.Type)
method.Func.Call([]reflect.Value{reflect.ValueOf(o), reflect.ValueOf("yanmou")})
}
}
func set(o interface{}) {
v := reflect.ValueOf(o)
elem := v.Elem()
name := elem.FieldByName("Name")
fmt.Println(v, "是否可以被修改:", name.CanSet())
name.SetString("xumeng33")
age := elem.FieldByName("Age")
fmt.Println(v, "是否可以被修改:", age.CanSet())
age.SetInt(24)
}
18.3、调用方法
package main
import (
"fmt"
"reflect"
)
func main() {
var person = Person{"xumeng03", 23}
StructCall(person)
FuncCall(Hello)
}
// 反射在设置结构体类型的属性时,只能设置被导出的属性!!!
type Person struct {
Name string
Age int
}
// 反射在获取结构体类型的方法时,只会返回被导出的方法!!!
func (p Person) Hello(str string) {
fmt.Println(p.Name, ": hello", str, "!")
}
func Hello(str string) {
fmt.Println(str, ": hello!")
}
func StructCall(o interface{}) {
v := reflect.ValueOf(o)
fmt.Println(v.Kind(), v.Type())
// 调用对象的方法
f := v.MethodByName("Hello")
f.Call([]reflect.Value{reflect.ValueOf("yanmou")})
}
func FuncCall(f interface{}) {
v := reflect.ValueOf(f)
fmt.Println(v.Kind(), v.Type())
v.Call([]reflect.Value{reflect.ValueOf("xumeng03")})
}