【Go语言】面向对象编程
一、面向对象编程概念
面向过程编程
- 整个过程分为若干步
- 每一步对应一个函数
- 函数之间要传递大量参数
范例:
package main import ( "errors" "fmt" "strconv" ) // 用户登录,获取信息,更新信息,列出信息 var message = "This is old message" func login(username string) (value int, isLogin bool, err error) { if username == "" { err = errors.New("user login faild") value = -1 isLogin = false return } else { fmt.Println(username, "login successful") return 10, true, nil } } func getInfo(isLogin bool) (value *string, err error) { if isLogin { fmt.Println(message) return &message, nil } else { return nil, errors.New("user not login") } } func updateInfo(userid int, isLogin bool, message *string, newInfo string) (err error) { if userid != -1 && isLogin { *message = strconv.Itoa(userid) + " modified to " + newInfo fmt.Println("message update to ", *message) return nil } else if userid == -1 || !isLogin { return errors.New("user not login") } else { return errors.New("Message is nil") } } func main() { uid, loginState, login_err := login("janzen") if login_err != nil { panic(login_err) } msg, get_err := getInfo(loginState) if get_err != nil { panic(get_err) } up_err := updateInfo(uid, loginState, msg, "New Message") if up_err != nil { panic(up_err) } fmt.Println(message) }输出结果:
PS F:\go\go_project\test> go run .\Function-oriented-programming\Function-oriented.go janzen login successful This is old message message update to 10 modified to New Message 10 modified to New Message
面向对象编程
- 把大量参数封装到结构体中
- 给结构体赋予方法,在成员方法内对结构体成员变量进行修改
- go语言面向对象的好处:打包参数、继承、面向接口编程
范例:
package main import ( "errors" "fmt" "strconv" ) var Message = "This is old message" type Client struct { UserName string Uid int LoginState bool } func Login(username string) (c *Client, err error) { if username == "" { err = errors.New("user login faild") c = nil return } else { fmt.Println(username, "login successful") c = &Client{username, 10, true} err = nil return } } func (c *Client) getInfo() (value *string, err error) { if c.LoginState { fmt.Println(Message) return &Message, nil } else { return nil, errors.New("user not login") } } func (c *Client) updateInfo(Message *string, newInfo string) (err error) { if c.Uid != -1 && c.LoginState && Message != nil { *Message = strconv.Itoa(c.Uid) + " modified to " + newInfo fmt.Println("message update to ", *Message) return nil } else if c.Uid == -1 || !c.LoginState { return errors.New("user not login") } else { return errors.New("Message is nil") } } func main() { c, login_err := Login("janzen") if login_err != nil { panic(login_err) } msg, get_err := c.getInfo() if get_err != nil { panic(get_err) } up_err := c.updateInfo(msg, "New Message") if up_err != nil { panic(up_err) } fmt.Println(Message) }输出结果:
PS F:\go\go_project\test> go run .\Object-oriented-programming\Object-oriented-programming.go janzen login successful This is old message message update to 10 modified to New Message 10 modified to New Message
二、构造函数
type User struct { Name string Age uint8 Sex byte } func main () { u1 := User{} // 构造一个空User, 各字段取相应的数据类型的默认值 u2 = new(User) //构造一个空User,并返回该User结构体的指针 }
自定义构造函数
type User struct { Name string Age int8 Sex byte } func NewUserDefault() *User { return &User{ Name: "", Age: -1, Sex: 3, } } func NewUser(name string, age int8,sex byte) *User { return &User{ Name: name, Age: age, Sex: sex, } }
单例模式
package main import "sync" var ( sUser *User uOnce sync.Once // 不同原子性操作,Once变量不可以共用,需要为每一个不同的原子性操作创建独立Once ) func NewUserDefault() *User { return &User{ Name: "", Age: -1, Sex: 3, } } func NewUser(name string, age int8, sex byte) *User { return &User{ Name: name, Age: age, Sex: sex, } } func getUser() *User { uOnce.Do(func() { //sync.Onec.DO 可以确保在并发情况下,下方代码块在整个go进程中只会被执行一次,原子性执行 if sUser == nil { sUser = NewUserDefault() } }) return sUser }
三、继承与重写
继承
go语言设计思想中没有真正的继承关系
通过嵌入匿名结构体,变相实现实现“继承”的功能
范例:
type User struct { Name string Age int8 Sex byte } type Student struct { User Grade byte Class byte } func main() { u := User{"janzen", 21, 1} s := Student{u, 3, 1} fmt.Printf("sNmae = %s, sAge = %d, sClass = %d", s.Name, s.Age, s.Class) }输出结果:
PS F:\go\go_project\test> go run .\Constructor\Constructor.go sNmae = janzen, sAge = 21, sClass = 1
重写
func (user User) level() int { return 10 } // 重写父类 User level方法 func (student Student) level() int { return student.User.level() + 100 // 调用父类方法 }
组合
type User struct { Name string Age int8 Sex byte } type Student struct { User Grade byte Class byte } // 通过组合使得 Persion 可以使用 User 和 Student 的全部方法和成员 type Persion struct { User Student }
四、泛型
未使用泛型
未使用泛型不同数据类型之间不能直接进行逻辑运算,哪怕同为整型,int8 与 int16 也不能直接进行逻辑运算
func main() { aInt := int(8) bInt8 := int8(17) sumInt := aInt + bInt8 }PS F:\go\go_project\test> go run .\FurnerStar\FurnerStar.go # command-line-arguments FurnerStar\FurnerStar.go:22:12: invalid operation: aInt + bInt8 (mismatched types int and int8) c常用方式:
func AddString(a, b string) string { return a + b } func AddInt(a, b int) int { return a + b } func AddInt8(a, b int8) int8 { return a + b } func main() { var aInt,bInt int = 8,10 var aInt8,bInt8 int8 = 7,19 sumInt := AddInt(aInt, bInt) sumInt8 := AddInt8(aInt8, bInt8) sumStr := AddString("test ", "test2") fmt.Println(sumInt, sumInt8, sumStr) }
使用泛型
type Addable interface { int|int8|int16|int32|int64| uint|uint8|uint16|uint32|uint64| float32|float64| string } func add[T Addable](a,b T)T{ return a+b } func main() { var aInt,bInt int = 8,10 var aInt8,bInt8 int8 = 7,19 sum1 := add(aInt,bInt) sum2 := add(aInt8,bInt8) sum3 := add("test ", "test2") fmt.Println(sum1,sum2,sum3) }