type和string
1.认识type关键字
type不光能定义结构体,接口还能定义自己的类型,比如说我定义一个自己的String
type String string
//构造函数 From写法其他编程语言比较常见
func From(str string) String{
return String(str)
}
func main() {
s := String.From("abc")
}
2.自己的String:类型方法 int变string
type String string
//构造函数 From写法其他编程语言比较常见
func FromInt(n int) String{
// return String(n) //错误写法
// return String(strconv.Itoa(n)) //使用strconv包下的方法将int转换为string
return String(fmt.Sprintf("%d",n)) //格式化,并把格式化内容返回 推荐这么写 也很好理解
}
// 返回长度
func (s String) Len() int {
return len(s)
}
func main() {
s := String.From(123)
fmt.Ptintln(s,s.Len())
//return String(n) 输出了'{' 这个符号刚好是ASCII码对应的123 说明了不行直接return String(n)不行
}
123 3
3.自己的String:遍历字符串 Each(*)
type String string
//构造函数 From写法其他编程语言比较常见
func From(str string) String{
return String(str)
}
//模仿Js 类函数 函数式参数,传的是一个函数
func (s String) Each(f func(item string)) {
for i := 0; i < len(s); i++ {
//fmt.Println(i,"",fmt.Sprintf("%c",str[i]))
f(fmt.Sprintf("%c",s[i]))
}
//for _, c := range s {
// f(fmt.Sprintf("%c",c))
//}
}
func main() {
str := String.From("abcde")
for i := 0; i < len(str); i++ {
fmt.Println(i,"",fmt.Sprintf("%c",str[i]))
}
str.Each(func(item string) {
fmt.Println(item)
})
}
4.自己的String:遍历字符串 (带中文)
一个中文字符占3个字节
type String string
//构造函数 From写法其他编程语言比较常见
func From(str string) String{
return String(str)
}
//模仿Js 类函数 函数式参数,传的是一个函数
func (s String) Each(f func(item string)) {
for _, c := range s {
f(fmt.Sprintf("%c",c))
}
}
func main() {
str := String.From("中abc")
str.Each(func(item string) {
fmt.Println(item)
})
}
中
a
b
c
5.从字符串中再认识下byte、rune
一般进行网络传输的时候使用字节传输
byte = uint8 ,代表了ASCII码字符集的一个字符
rune = int32 ,当处理中文、日文、韩文等复合字符集时,使用rune 。也就是Unicode字符集(utf-8、utf16是编码规则)
自定义struct
6.自定义struct、构造函数
Go语言都是值传递
package Object
type User struct {
Id,Sex int
Name string
}
func NewUser() User {
return User{}
}
func change(u Object.User) Object.User {
u.Id = 202
return u
}
func main() {
u := Object.NewUser()
u.Id = 101
//一般代码不会这么写,通常使用指针
u = change(u)
//fmt.Println(u)
fmt.Printf("%#v\n", &u)
}
7.使用指针struct
type User struct {
Id,Sex int
Name string
}
func NewUser() *User {
//两种写法
return new(User)
//return &User
}
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) //{0 0 } <nil>
u := Object.NewUser()
u.Id = 101
change(u)
fmt.Printf("%p\n", u)
}
8.构造函数的技巧:任意设置属性值(*)
我之前的lowB写法
func NewUser(id int) User {
return User{
Id: id,
}
}
带佬写法
type User struct {
Id,Sex int
Name string
}
//有选择性的对ID进行赋值
func NewUser(f func(u *User)) *User {
u := new(User)
f(u)
return u
}
//WithUserID :NewUser 中 参数的构造函数
func WithUserID(id int) func(u *User) {
return func(u *User) {
u.Id = id
}
}
func main() {
u := Object.NewUser(
Object.WithUserID(120),
)
fmt.Println(u) //&{120 0 }
}
9.构造函数技巧:可变参数(*)
上面的代码有一些小遗憾,参数是必填的,不填会报错,zhei次要使用可变参数
type User struct {
Id,Sex int
Name string
}
//有选择性的对ID进行赋值
//...表示可变参数,fs是一个切片
func NewUser(fs ... func(u *User)) *User {
u := new(User)
for _, f := range fs {
f(u)
}
return u
}
//WithUserID :NewUser 中 参数的构造函数
func WithUserID(id int) func(u *User) {
return func(u *User) {
u.Id = id
}
}
//缺点是代码量增加了,但是调用方便了
func WithUserNmae(name string) func(u *User) {
return func(u *User) {
u.Name = name
}
}
func main() {
//技术,两害取其精 看自己取舍了
u := Object.NewUser(
Object.WithUserNmae("Jahon"),
//可以不填,也可以填
Object.WithUserID(120),
)
fmt.Println(u) //&{120 0 }
}
10.构造函数技巧:进一步提升逼格(🐂的)
反复封装,绕的有些晕
package Object
import "fmt"
type UserAttrFunc func(*User) //用来设置user属性的 函数类型
type UserAttrFuncs []UserAttrFunc
// UserAttrFunc 的构造函数
func (this UserAttrFuncs) apply(u *User) {
//好比执行了 func(*User){} ()
for _, f := range this {
f(u)
}
}
type User struct {
Id,Sex int
Name string
}
//有选择性的对ID进行赋值
//...表示可变参数,fs是一个切片
func NewUser(fs ... UserAttrFunc) *User {
u := new(User)
//这里需要进行一次强制转换
UserAttrFuncs(fs).apply(u)
fmt.Printf("%T\n",fs) //[]Object.UserAttrFunc 切片
return u
}
//WithUserID :NewUser 中 参数的构造函数
func WithUserID(id int) UserAttrFunc {
return func(u *User) {
u.Id = id
}
}
//缺点是代码量增加了,但是调用方便了
func WithUserNmae(name string) UserAttrFunc {
return func(u *User) {
u.Name = name
}
}
func main() {
//技术,两害取其精
u := Object.NewUser(
Object.WithUserNmae("Jathon"),
//可以不填,也可以填
Object.WithUserID(120),
)
fmt.Println(u) //&{120 0 }
}
map
11.基本使用、模拟User实体的创建
package Map
type User map[string]string
func NewUser() User {
return make(map[string]string)
}
//map是引用类型,传的是地址的值,复制也是地址的值,所以可以直接改,没有必要写指针
func change(u Map.User) {
u["id"] = "404"
}
func main() {
//map的 key值必须是可比较的
//var user map[string]string
//user = make(map[string]string)
//user["id"] = "101"
//fmt.Println(user)
u :=Map.NewUser()
u["id"] = "101"
u["name"] = "Jathon"
fmt.Println(u) //map[id:101 name:Jathon]
change(u)
fmt.Println(u) //map[id:404 name:Jathon]
}
12.设置值、链式调用
package Map
type User map[string]interface{}
func NewUser() User {
return make(map[string]interface{})
}
func (u User) With(k string,v interface{}) User {
u[k] = v
return u
}
func main() {
//普通调用
//func (u User) With(k string,v interface{}) {
// u[k] = v
//}
u :=Map.NewUser()
u.With("id","101")
u.With("name","Jathon")
fmt.Println(u)
//链式调用(比较特殊的写法)
u.With("id","101").
With("name","Jathon")
}
13.遍历map、按自己的格式打印map
func (u User) String() {
for k, v := range u {
fmt.Printf("%v->%v\n",k,v)
}
}
func main() {
u :=Map.NewUser()
//链式调用
u.With("id","101").
With("name","Jathon")
u.String()
}
下面这种算是种特殊的写法了,场景是老子偏要使用Println这种形式,它返回的是string,在运行Println时会主动调用这个方法。
func (u User) String() string {
str := ""
for k, v := range u {
str+= fmt.Sprintf("%v->%v\n",k,v)
}
return str
}
func main() {
u :=Map.NewUser()
//链式调用
u.With("id","101").
With("name","Jathon")
fmt.Println(u)
}
14.排序Map Key、Sort包初步使用
//思路是把map的key放到切片中,用sort包进行排序
func (u User) Fields() []string {
keys :=[]string{}
for k, _ := range u {
keys = append(keys, k)
}
//1.0写法
sort.Strings(keys)
//更妥帖的写法(强转一下)
sort.Strings(sort.StringSlice(keys))
//点进sort包可以看到最原始写法(写全)
sort.Sort(sort.StringSlice(keys))
//倒排
sort.Sort(sort.Reverse(sort.StringSlice(keys)))
return keys
}
func (u User) String() string {
str := ""
for index, k := range u.Fields() {
str+= fmt.Sprintf("%d、%v->%v\n",index+1,k,u[k])
}
return str
}
func main() {
u := Map.NewUser()
//链式调用
u.With("id", "101").
With("name", "Jathon").
With("sex", "male").
With("age", 18)
fmt.Println(u)
}
1、sex->male
2、name->Jathon
3、id->101
4、age->18
15.多个map之间的排序方法
func main() {
u1 := Map.NewUser()
u1.With("id", "101").
With("name", "Jathon").
With("age", 18)
u2 := Map.NewUser()
u2.With("id", "114514").
With("name", "李田所").
With("age", 24)
u3 := Map.NewUser()
u3.With("id", "6324").
With("name", "孙笑川").
With("age", 33)
users := []Map.User{}
users = append(users, u1, u2, u3)
//a, b c=人类 断定c是a
//i和j是索引
//sort.Slice 不保证相等情况下顺序
//sort.SliceStable 更严谨
sort.SliceStable(users, func(i, j int) bool {
//断言功能 专针对于interface 断言成int
age1 := users[i]["age"].(int)
age2 := users[j]["age"].(int)
return age1 < age2
})
fmt.Println(users)
}