go语言学习笔记(三)

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()
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

phpstory

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值