本篇概要:
- 1. type 关键字;
- 2. 定制的 String、类型方法、int 变 string;
- 3. 定制的 String:遍历字符串、Each;
- 4. 定制的 String:遍历字符串(带中文);
- 5. 从字符串中再认识下 byte、rune;
- 6. 自定义 struct、所谓的构造函数;
- 7. 使用指针 struct;
- 8. 构造函数技巧:任意设置属性值;
- 9. 构造函数技巧:可变参数;
- 10. 构造函数技巧:进一步封装;
- 11. map强化、基本使用、模拟 User 实体的创建;
- 12. 设置值、链式调用;
- 13. 遍历 map、按格式打印 map;
- 14. 排序 Map Key、Sort 包的初步使用;
- 15. 多个 map 之间的排序方法;
概要:
- 设计模式 web、中间件(consul、etcd、tidb)、偏底层(docker、k8s)
- httpserver、rpc \ grpc、http3(quic)、go-micro、gokit
- 模板、nginx、gin、gin++
IDE 配置:
1. type 关键字;
# 进入 /Users/go/go2/
go mod init goplus
- 文件
/Users/go/go2/src/String/String.go
package String
type String string //自己定义的 string
// 返回自定义的 String
func From(str string) (String) {
// String 强制转化,本质是一样的
return String(str)
}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/String"
)
func main() {
s := String.From("abc")
fmt.Println(s)
}
2. 定制的 String、类型方法、int 变 string;
- 文件
/Users/go/go2/src/String/String.go
package String
import (
"fmt"
)
type String string //自己定义的 string
// 实现类似于类方法的函数
// 返回长度
func (this String) Len() (int) {
return len(this)
}
// 返回自定义的 String
func From(str string) (String) {
// String 强制转化,本质是一样的
return String(str)
}
func FromInt(n int) (String) {
// 当成 string 转,直接会当成 ASCII 码值
// 所以调用方法会返回 "{",ASCII 123 对应的符号
// return String(n)
// 第一种写法:内置转化方法
// return String(strconv.Itoa(n))
// 第二种写法
return String(fmt.Sprintf("%d", n))
}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/String"
)
func main() {
// s := String.From("abc")
s := String.FromInt(123)
fmt.Println(s)
fmt.Println(s.Len()) //类方法
}
3. 定制的 String:遍历字符串、Each;
- 文件
/Users/go/go2/src/String/String.go
package String
import (
"fmt"
)
type String string //自己定义的 string
// 实现类似于类方法的函数
// 返回长度
func (this String) Len() (int) {
return len(this)
}
// !!遍历(函数里的参数是可以传函数的)
func (this String) Each(f func(item string)) {
for i :=0; i < len(this); i++ {
// fmt.Println(i, ", ",fmt.Sprintf("%c", this[i]))
f(fmt.Sprintf("%c", this[i]))
}
}
// 返回自定义的 String
func From(str string) (String) {
// String 强制转化,本质是一样的
return String(str)
}
func FromInt(n int) (String) {
// 当成 string 转,直接会当成 ASCII 码值
// 所以调用方法会返回 "{",ASCII 123 对应的符号
// return String(n)
// 第一种写法:内置转化方法
// return String(strconv.Itoa(n))
// 第二种写法
return String(fmt.Sprintf("%d", n))
}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/String"
)
func main() {
s := String.From("abcde")
// s := String.FromInt(123)
// 遍历
for i :=0; i < len(s); i++ {
// 打印出 ASCII 码
// fmt.Println(i, ", ",s[i])
// go 没有 char 类型
// %c 打印 char
// fmt.Println(i, ", ",fmt.Sprintf("%c", s[i]))
}
// 调用遍历
s.Each(func(item string) {
fmt.Println(item) // 返回 abcde
})
}
4. 定制的 String:遍历字符串(带中文);
- 文件
/Users/go/go2/src/String/String.go
package String
import (
"fmt"
)
type String string //自己定义的 string
// 实现类似于类方法的函数
// 返回长度
func (this String) Len() (int) {
return len(this)
}
// 遍历(函数里的参数是可以传函数的)
func (this String) Each(f func(item string)) {
for i :=0; i < len(this); i++ {
// fmt.Println(i, ", ",fmt.Sprintf("%c", this[i]))
f(fmt.Sprintf("%c", this[i]))
}
}
// !!遍历中文
func (this String) EachC(f func(item string)) {
for _, c := range this {
f(fmt.Sprintf("%c", c))
}
}
// 返回自定义的 String
func From(str string) (String) {
// String 强制转化,本质是一样的
return String(str)
}
func FromInt(n int) (String) {
// 当成 string 转,直接会当成 ASCII 码值
// 所以调用方法会返回 "{",ASCII 123 对应的符号
// return String(n)
// 第一种写法:内置转化方法
// return String(strconv.Itoa(n))
// 第二种写法
return String(fmt.Sprintf("%d", n))
}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/String"
)
func main() {
s := String.From("我123")
// 返回
//0 我
//3 1
//4 2
//5 3
//for index,c := range s {
// fmt.Println(index, " ", fmt.Sprintf("%c", c))
//}
s.EachC(func(item string) {
fmt.Println(item) // 返回 "我123"
})
}
5. 从字符串中再认识下 byte、rune;
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/String"
)
func main() {
s := String.From("我123")
for i:=0; i<len(s); i++ {
// fmt.Println(i, "", s[i]) // 打印原始字节
// fmt.Println(i, "", fmt.Sprintf("%T", s[i])) // 打印字节的类型(无符号int8)
}
// 网络编程和数据传输的时候都是使用"字节" byte
// 字符串的本质就是字节,虽然表达形式不同
// uint 类型就是 byte 型,代表 ASCII 码字符集的一个字符
// 当处理中文、日文、韩文等符合字符时,使用 rune 就是 int 32,也就是 Unicode 字符集(utf8 是编码规则)
fmt.Println([]byte(s)) // [230 136 145 49 50 51]
fmt.Println([]int32(s)) // [25105 49 50 51]
fmt.Println([]rune(s)) // int32 的别名 rune,[25105 49 50 51]
fmt.Printf("%c", 25105) // 我
for _, c :=range s {
//25105
//49
//50
//51
fmt.Println(c) // 字符串遍历,是 unicode 字符集
}
}
6. 自定义 struct、所谓的构造函数;
- 文件
/Users/go/go2/src/Object/User.go
package Object
type User struct {
Id, Gender int
Name string
}
func NewUser() (User) {
return User{}
}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/Object"
)
// u 形参参数名
func change(u Object.User) {
u.Id = 202
}
// 有效,但是一般代码不会这么写,都会用指针
func change2(u Object.User) Object.User {
u.Id = 202
return u
}
func main() {
u := Object.NewUser()
// fmt.Println(u) // 默认打印每一项属性的 0 值(初始值):{0 0 }
//fmt.Printf("%v", u) // 和上面结果一样
//fmt.Printf("%+v", u) // 显示 属性的名称:{Id:0 Gender:0 Name:}
// 修改属性
u.Id = 101
//change(u) // 修改无效
//u = change2(u) // 修改有效:{Id:202 Gender:0 Name:}{
//fmt.Printf("%+v", u)
fmt.Printf("%p", &u) // 看地址:0xc0000a6020
}
7. 使用指针 struct;
常见的方式是:一律采用指针对 struct 进行初始化
- 文件
/Users/go/go2/src/Object/User.go
package Object
type User struct {
Id, Gender int
Name string
}
func NewUser() (*User) {
return new (User)
// return &User{}
}
//func NewUser() (User) {
// return User{}
//}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/Object"
)
func change(u *Object.User) {
u.Id = 202
fmt.Printf("%p\n", u)
}
func main() {
//uu := Object.User{}
//fmt.Println(uu) // {0 0 }
//
//u := Object.NewUser()
//fmt.Println(u) // &{0 0 }
//
//
//var u1 Object.User // 如此定义, 已经开辟了值
//var u2 *Object.User // 定义指针变量,得进行初始化
//fmt.Println(u1, u2) // {00 } <nil>
u := Object.NewUser()
change(u) // 0xc00000c060
fmt.Printf("%p\n", u) // 0xc00000c060
fmt.Println(u) // &{202 0 }
// struct 传参尽量使用指针,仅仅是地址的值,不会是 struct 里的 内容
// go 里面是按值传递,就算传的是指针,不会复制 struct 本身内容,但是会复制地址的值
// 地址的值对应的地址是不一样的
}
8. 构造函数技巧:任意设置属性值;
- 文件
/Users/go/go2/src/Object/User.go
package Object
type User struct {
Id, Gender int
Name string
}
// 有选择性的对 Id 进行赋值
func NewUser(f func(u *User)) (*User) {
u := new (User)
f(u)
return u
}
// 用来构造上面的 f 函数
//仅仅返回 function 而不是执行结果
func WithUserId(id int) (f func(u *User)) {
return func(u *User) {
u.Id = id
}
}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/Object"
)
func main() {
u := Object.NewUser(
Object.WithUserId(120),
)
fmt.Println(u) // &{120 0 }
}
9. 构造函数技巧:可变参数;
- 文件
/Users/go/go2/src/Object/User.go
package Object
type User struct {
Id int
Name string
Gender byte
}
// 有选择性的进行赋值(可变参数,参数类型是 function)
func NewUser(fs ...func(u *User)) (*User) {
u := new (User)
for _, f := range fs {
f(u)
}
return u
}
- 文件
/Users/go/go2/src/Object/UserAttrs.go
package Object
func WithUserId(id int) (f func(u *User)) {
return func(u *User) {
u.Id = id
}
}
func WithUserName(name string) (f func(u *User)) {
return func(u *User) {
u.Name = name
}
}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/Object"
)
func main() {
u := Object.NewUser(
Object.WithUserId(120),
Object.WithUserName("hua"),
)
fmt.Println(u)
}
10. 构造函数技巧:进一步封装;
- 文件
/Users/go/go2/src/Object/UserAttrs.go
package Object
// type UserAttrFunc func(u *User)
type UserAttrFunc func(*User) // 用来设置 User 属性的函数类型,参数可省略
type UserAttrFuncs []UserAttrFunc
// 类方法
//func (this UserAttrFunc) apply (u *User){
// this(u)
//}
func (this UserAttrFuncs) apply (u *User){
for _, f := range this {
f(u)
}
}
func WithUserId(id int) (UserAttrFunc) {
return func(u *User) {
u.Id = id
}
}
func WithUserName(name string) (UserAttrFunc) {
return func(u *User) {
u.Name = name
}
}
- 文件
/Users/go/go2/src/Object/User.go
package Object
type User struct {
Id int
Name string
Gender byte
}
// 有选择性的进行赋值(可变参数,参数类型是 function)
func NewUser(fs ...UserAttrFunc) (*User) {
u := new (User)
//for _, f := range fs {
// f.apply(u)
//}
UserAttrFuncs(fs).apply(u)
// fmt.Printf("%T", fs) // 查看类型
return u
}
11. map强化、基本使用、模拟 User 实体的创建;
- 文件
/Users/go/go2/src/Map/User.go
package Map
// 自定义类型
type User map[string]string
func NewUser() (User) {
// 初始化 map
return make(map[string]string)
}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/Map"
)
// 几个类型: map、chan、slice
func change(u Map.User) {
u["id"] = "404"
}
func main() {
//var user map[string]string
//
初始化map
//user = make(map[string]string)
//
//user["id"] = "101"
//
//fmt.Println(user)
u := Map.NewUser()
u["id"] = "202"
u["name"] = "hua"
change(u) // 可以改值
// map 引用类型、传参数传的是所对应地址的值(go都是按值传递)
fmt.Println(u)
}
12. 设置值、链式调用;
- 文件
/Users/go/go2/src/Map/User.go
package Map
// 自定义类型
type User map[string]interface{}
func (this User) With(k string, v interface{}) (User){
this[k] = v
return this
}
func NewUser() (User) {
// 初始化 map
return make(map[string]interface{})
}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/Map"
)
func main() {
u := Map.NewUser()
//u.With("id", "212")
//u.With("name", "hua")
// 链式调用
u.With("id", 212).
With("name", "hua")
fmt.Println(u)
}
13. 遍历 map、按格式打印 map;
- 文件
/Users/go/go2/src/Map/User.go
package Map
import "fmt"
// 自定义类型
type User map[string]interface{}
func (this User) With(k string, v interface{}) (User){
this[k] = v
return this
}
//func (this User) String() {
// for k, v := range this {
// fmt.Printf("%v->%v\n", k, v)
// }
//}
// 没有 string 方法,有默认的打印值
// 有 string 方法 直接调用
// 并不是每次按顺序打印
func (this User) String() string {
str := ""
for k, v := range this {
str +=fmt.Sprintf("%v->%v\n", k, v)
}
return str
}
func NewUser() (User) {
// 初始化 map
return make(map[string]interface{})
}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/Map"
)
func main() {
u := Map.NewUser()
// 链式调用
u.With("id", 212).
With("name", "hua")
//fmt.Println(u) // map[id:212 name:hua]
// u.String() // id->212name->hua
fmt.Println(u) // 有定义的string方法,则打印出:id->212name->hua
}
14. 排序 Map Key、Sort 包的初步使用;
- 文件
/Users/go/go2/src/Map/User.go
package Map
import (
"fmt"
"sort"
)
// 自定义类型
type User map[string]interface{}
func (this User) With(k string, v interface{}) (User){
this[k] = v
return this
}
func (this User) String() string {
str := ""
for index, k := range this.Fields() {
str +=fmt.Sprintf("%d、%v->%v\n", index+1, k, this[k])
}
return str
}
// 返回切片
func (this User) Fields() ([]string) {
keys := []string{}
for k, _ := range this{
keys = append(keys, k)
}
// sort.Strings(sort.StringSlice(keys)) // 正排序
// sort.Strings(keys) // 正排序
// sort.Sort(sort.StringSlice(keys)) // 正排序
sort.Sort(sort.Reverse(sort.StringSlice(keys))) // 倒叙(全写)
return keys
//1、age->27
//2、gender->male
//3、id->212
//4、name->hua
}
func NewUser() (User) {
// 初始化 map
return make(map[string]interface{})
}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/Map"
)
func main() {
u := Map.NewUser()
// 链式调用
u.With("id", 212).
With("name", "hua").
With("gender", "male").
With("age", 27)
fmt.Println(u)
}
15. 多个 map 之间的排序方法;
- 文件
/Users/go/go2/src/Map/User.go
package Map
import "sort"
// 自定义类型
type User map[string]interface{}
func (this User) With(k string, v interface{}) (User){
this[k] = v
return this
}
//func (this User) String() string {
// str := ""
// for index, k := range this.Fields() {
// str +=fmt.Sprintf("%d、%v->%v\n", index+1, k, this[k])
// }
// return str
//}
// 返回切片
func (this User) Fields() ([]string) {
keys := []string{}
for k, _ := range this{
keys = append(keys, k)
}
// sort.Strings(sort.StringSlice(keys)) // 正排序
// sort.Strings(keys) // 正排序
// sort.Sort(sort.StringSlice(keys)) // 正排序
sort.Sort(sort.Reverse(sort.StringSlice(keys))) // 倒叙(全写)
return keys
//1、age->27
//2、gender->male
//3、id->212
//4、name->hua
}
func NewUser() (User) {
// 初始化 map
return make(map[string]interface{})
}
- 文件
/Users/go/go2/src/main.go
package main
import (
"fmt"
"goplus/src/Map"
"sort"
)
func main() {
u1 := Map.NewUser()
u1.With("id", 212).
With("name", "hua").
With("age", 33)
u2 := Map.NewUser()
u2.With("id", 12).
With("name", "zhang").
With("age", 27)
u3 := Map.NewUser()
u3.With("id", 121).
With("name", "wang").
With("age", 50)
users := []Map.User{}
users = append(users, u1, u2, u3)
sort.Slice(users, func(i, j int) bool {
age1 := users[i]["age"]. (int) // 断言,针对 interface
age2 := users[i]["age"]. (int)
return age1>age2
})
fmt.Println(users) // [map[age:33 id:212 name:hua] map[age:27 id:12 name:zhang] map[age:50 id:121 name:wang]]
}