golang学习笔记
一、匿名函数
package main
import (
"fmt"
)
func main() {
res := func(n1 int, n2 int) int {
return n1 + n2
}(10, 20)
fmt.Println(res)
}
等价于《=》
func main() {
res := func(n1 int, n2 int) int {
return n1 + n2
}
res2 := res(10,20)
fmt.Println(res2)
}
二、闭包
闭包就是一个函数和与其相关的引用坏境组合的一个整体(实体)
package main
import (
"fmt"
)
func addUpper() func(int) int {
var n int = 10
return func(x int) int {
n = n + x
return n
}
}
func main() {
f := addUpper()
fmt.Println(f(1))
fmt.Println(f(2))
fmt.Println(f(3))
}
这一块就是闭包
var n int = 10
return func(x int) int {
n = n + x
return n
}
三、字符串的系统函数
1、len(str)
2、r := []rune(str) 字符串遍历
3、字符串转整型
n, err := strconv.Atoi("12")
if err != nil {
fmt.Println("转换错误")
} else {
fmt.Println(n)
}
4、整型转字符串
str := strconv.Itoa(11233)
fmt.Printf("%v %T", str, str)
5、判断子串是否在字符串中
b := strings.Contains("seafood", "foo")
fmt.Printf("%v", b)
四、错误处理
defer func() {
err := recover()
if err != nil {
fmt.Println("err = ", err)
}
}()
五、string是不可变的,不能通过s[0] = "g"来修改
如果改变使用byte rune
func main() {
str := "phpstory"
slice := str[6:]
fmt.Println(slice)
arr1 := []byte(str)
arr1[0] = 'z'
str = string(arr1)
fmt.Println(str)
arr2 := []rune(str)
arr2[0] = '北'
str = string(arr2)
fmt.Println(str)
}
六、结构体
package main
import "fmt"
type Person struct {
Name string
}
func (p Person) test() {
fmt.Println("test() name", p.Name)
}
func main() {
var p Person
p.Name = "tom"
p.test()
}
七、工厂模式
model文件下面的代码student.go
package model
type student struct {
Name string
score float64
}
func NewStudent(n string, s float64) *student {
return &student{
Name: n,
score: s,
}
}
//小写的score不能直接访问,所以要写方法
func (s *student) GetScore() float64 {
return s.score
}
要引入文件的代码
package main
import (
"fmt"
"learngo/model"
)
func main() {
var stu = model.NewStudent("tom~", 88.8)
fmt.Println(*stu)
fmt.Println(stu.Name, stu.GetScore())
}
另外的例子,面向对象的封装persion.go和main.go
package model
import "fmt"
type persion struct {
Name string
age int
sal float64
}
func NewPersion(name string) *persion {
return &persion{
Name: name,
}
}
func (p *persion) SetAge(age int) {
if age > 0 && age < 150 {
p.age = age
} else {
fmt.Println("年龄范围不正确。。。")
}
}
func (p *persion) GetAge() int {
return p.age
}
func (p *persion) SetSal(sal float64) {
if sal >= 3000 && sal <= 30000 {
p.sal = sal
} else {
fmt.Println("薪水范围不正确。。。")
}
}
func (p *persion) GetSal() float64 {
return p.sal
}
package main
import (
"fmt"
"learngo/model"
)
func main() {
p := model.NewPersion("smith")
p.SetAge(18)
p.SetSal(5000)
fmt.Println(p)
fmt.Println(p.Name, p.GetAge(), p.GetSal())
}
八、接口
package main
import (
"fmt"
)
//声明/定义一个接口
type Usb interface {
//声明了两个没有实现的方法
Start()
Stop()
}
type Phone struct {
name string
}
//让Phone 实现 Usb接口的方法
func (p Phone) Start() {
fmt.Println(p.name, "手机开始工作。。。")
}
func (p Phone) Stop() {
fmt.Println(p.name, "手机停止工作。。。")
}
func (p Phone) Call() {
fmt.Println(p.name, "手机 在打电话..")
}
type Camera struct {
name string
}
//让Camera 实现 Usb接口的方法
func (c Camera) Start() {
fmt.Println(c.name, "相机开始工作。。。")
}
func (c Camera) Stop() {
fmt.Println(c.name, "相机停止工作。。。")
}
type Computer struct {
}
func (computer Computer) Working(usb Usb) {
usb.Start()
//如果usb是指向Phone结构体变量,则还需要调用Call方法
//类型断言..[注意体会!!!]
if phone, ok := usb.(Phone); ok {
phone.Call()
}
usb.Stop()
}
func main() {
//定义一个Usb接口数组,可以存放Phone和Camera的结构体变量
//这里就体现出多态数组
var usbArr [3]Usb
usbArr[0] = Phone{"vivo"}
usbArr[1] = Phone{"小米"}
usbArr[2] = Camera{"尼康"}
//遍历usbArr
//Phone还有一个特有的方法call(),请遍历Usb数组,如果是Phone变量,
//除了调用Usb 接口声明的方法外,还需要调用Phone 特有方法 call. =》类型断言
var computer Computer
for _, v := range usbArr {
computer.Working(v)
fmt.Println()
}
//fmt.Println(usbArr)
}
九、文件
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
//打开文件
//概念说明: file 的叫法
//1. file 叫 file对象
//2. file 叫 file指针
//3. file 叫 file 文件句柄
file, err := os.Open("go.mod")
if err != nil {
fmt.Println("open file err=", err)
}
//当函数退出时,要及时的关闭file
defer file.Close() //要及时关闭file句柄,否则会有内存泄漏.
// 创建一个 *Reader ,是带缓冲的
/*
const (
defaultBufSize = 4096 //默认的缓冲区为4096
)
*/
reader := bufio.NewReader(file)
fmt.Println("文件读取开始...")
//循环的读取文件的内容
for {
str, err := reader.ReadString('\n') // 读到一个换行就结束
if err == io.EOF { // io.EOF表示文件的末尾
break
}
//输出内容
fmt.Printf(str)
}
fmt.Println("文件读取结束...")
}
十、写入文件
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
//创建一个新文件,写入内容 5句 "hello, Gardon"
//1 .打开文件 ./abc.txt
filePath := "./abc.txt"
//追加写使用 file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_APPEND, 0666)
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
fmt.Printf("open file err=%v\n", err)
return
}
//及时关闭file句柄
defer file.Close()
//准备写入5句 "hello, Gardon"
str := "hello,Gardon\r\n" // \r\n 表示换行
//写入时,使用带缓存的 *Writer
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.WriteString(str)
}
//因为writer是带缓存,因此在调用WriterString方法时,其实
//内容是先写入到缓存的,所以需要调用Flush方法,将缓冲的数据
//真正写入到文件中, 否则文件中会没有数据!!!
writer.Flush()
fmt.Println("写入成功。。。")
}
十一、统计文件中字符的个数
package main
import (
"bufio"
"fmt"
"io"
"os"
)
//定义一个结构体,用于保存统计结果
type CharCount struct {
ChCount int // 记录英文个数
NumCount int // 记录数字的个数
SpaceCount int // 记录空格的个数
OtherCount int // 记录其它字符的个数
}
func main() {
//思路: 打开一个文件, 创一个Reader
//每读取一行,就去统计该行有多少个 英文、数字、空格和其他字符
//然后将结果保存到一个结构体
fileName := "./abc.txt"
file, err := os.Open(fileName)
if err != nil {
fmt.Printf("open file err=%v\n", err)
return
}
defer file.Close()
//定义个CharCount 实例
var count CharCount
//创建一个Reader
reader := bufio.NewReader(file)
//开始循环的读取fileName的内容
for {
str, err := reader.ReadString('\n')
if err == io.EOF { //读到文件末尾就退出
break
}
//遍历 str ,进行统计
for _, v := range str {
switch {
case v >= 'a' && v <= 'z':
fallthrough //穿透
case v >= 'A' && v <= 'Z':
count.ChCount++
case v == ' ' || v == '\t' || v == '\n' || v == '\r':
count.SpaceCount++
case v >= '0' && v <= '9':
count.NumCount++
default:
count.OtherCount++
}
}
}
fmt.Println()
//输出统计的结果看看是否正确
fmt.Printf("字符的个数为=%v 数字的个数为=%v 空格的个数为=%v 其它字符个数=%v",
count.ChCount, count.NumCount, count.SpaceCount, count.OtherCount)
fmt.Println()
}
十二、json序列化
package main
import (
"encoding/json"
"fmt"
)
//定义一个结构体
type Monster struct {
Name string `json:"monster_name"` //反射机制
Age int `json:"monster_age"`
Birthday string //....
Sal float64
Skill string
}
func testStruct() {
//演示
monster := Monster{
Name: "牛魔王",
Age: 500,
Birthday: "2011-11-11",
Sal: 8000.0,
Skill: "牛魔拳",
}
//将monster 序列化
data, err := json.Marshal(&monster) //..
if err != nil {
fmt.Printf("序列号错误 err=%v\n", err)
}
//输出序列化后的结果
fmt.Printf("monster序列化后=%v\n", string(data))
}
//将map进行序列化
func testMap() {
//定义一个map
var a map[string]interface{}
//使用map,需要make
a = make(map[string]interface{})
a["name"] = "红孩儿"
a["age"] = 30
a["address"] = "洪崖洞"
//将a这个map进行序列化
//将monster 序列化
data, err := json.Marshal(a)
if err != nil {
fmt.Printf("序列化错误 err=%v\n", err)
}
//输出序列化后的结果
fmt.Printf("a map 序列化后=%v\n", string(data))
}
//演示对切片进行序列化, 我们这个切片 []map[string]interface{}
func testSlice() {
var slice []map[string]interface{}
var m1 map[string]interface{}
//使用map前,需要先make
m1 = make(map[string]interface{})
m1["name"] = "jack"
m1["age"] = "7"
m1["address"] = "北京"
slice = append(slice, m1)
var m2 map[string]interface{}
//使用map前,需要先make
m2 = make(map[string]interface{})
m2["name"] = "tom"
m2["age"] = "20"
m2["address"] = [2]string{"墨西哥", "夏威夷"}
slice = append(slice, m2)
//将切片进行序列化操作
data, err := json.Marshal(slice)
if err != nil {
fmt.Printf("序列化错误 err=%v\n", err)
}
//输出序列化后的结果
fmt.Printf("slice 序列化后=%v\n", string(data))
}
//对基本数据类型序列化,对基本数据类型进行序列化意义不大
func testFloat64() {
var num1 float64 = 2345.67
//对num1进行序列化
data, err := json.Marshal(num1)
if err != nil {
fmt.Printf("序列化错误 err=%v\n", err)
}
//输出序列化后的结果
fmt.Printf("num1 序列化后=%v\n", string(data))
}
func main() {
fmt.Println()
//演示将结构体, map , 切片进行序列号
testStruct()
testMap()
testSlice() //演示对切片的序列化
testFloat64() //演示对基本数据类型的序列化
fmt.Println()
}
反序列化
package main
import (
"encoding/json"
"fmt"
)
//定义一个结构体
type Monster struct {
Name string
Age int
Birthday string //....
Sal float64
Skill string
}
//演示将json字符串,反序列化成struct
func unmarshalStruct() {
//说明str 在项目开发中,是通过网络传输获取到.. 或者是读取文件获取到
str := "{\"Name\":\"牛魔王~~~\",\"Age\":500,\"Birthday\":\"2011-11-11\",\"Sal\":8000,\"Skill\":\"牛魔拳\"}"
//定义一个Monster实例
var monster Monster
err := json.Unmarshal([]byte(str), &monster)
if err != nil {
fmt.Printf("unmarshal err=%v\n", err)
}
fmt.Printf("反序列化后 monster=%v monster.Name=%v \n", monster, monster.Name)
}
//将map进行序列化
func testMap() string {
//定义一个map
var a map[string]interface{}
//使用map,需要make
a = make(map[string]interface{})
a["name"] = "红孩儿~~~~~~"
a["age"] = 30
a["address"] = "洪崖洞"
//将a这个map进行序列化
//将monster 序列化
data, err := json.Marshal(a)
if err != nil {
fmt.Printf("序列化错误 err=%v\n", err)
}
//输出序列化后的结果
//fmt.Printf("a map 序列化后=%v\n", string(data))
return string(data)
}
//演示将json字符串,反序列化成map
func unmarshalMap() {
//str := "{\"address\":\"洪崖洞\",\"age\":30,\"name\":\"红孩儿\"}"
str := testMap()
//定义一个map
var a map[string]interface{}
//反序列化
//注意:反序列化map,不需要make,因为make操作被封装到 Unmarshal函数
err := json.Unmarshal([]byte(str), &a)
if err != nil {
fmt.Printf("unmarshal err=%v\n", err)
}
fmt.Printf("反序列化后 a=%v\n", a)
}
//演示将json字符串,反序列化成切片
func unmarshalSlice() {
str := "[{\"address\":\"北京\",\"age\":\"7\",\"name\":\"jack\"}," +
"{\"address\":[\"墨西哥\",\"夏威夷\"],\"age\":\"20\",\"name\":\"tom\"}]"
//定义一个slice
var slice []map[string]interface{}
//反序列化,不需要make,因为make操作被封装到 Unmarshal函数
err := json.Unmarshal([]byte(str), &slice)
if err != nil {
fmt.Printf("unmarshal err=%v\n", err)
}
fmt.Printf("反序列化后 slice=%v\n", slice)
}
func main() {
unmarshalStruct()
unmarshalMap()
unmarshalSlice()
}