go学习笔记-面向对象(Methods, Interfaces)

面向对象(Methods, Interfaces)

Method

method是附属在一个给定的类型上的,他的语法和函数的声明语法几乎一样,只是在func后面增加了一个receiver(也就是method所依从的主体)。

语法

func (r ReceiverType) funcName(parameters) (results)

示例

type rectangle struct {
	width  float64
	heigth float64
}

func (receiver rectangle) area() float64 {
	return receiver.width * receiver.heigth
}

func main(){
	rect := rectangle{heigth: 12, width: 12}
	area := rect.area()
	fmt.Println(area)
}

注意

  • 接收者不一样,那么method就不一样
  • method里面可以访问接收者的字段
  • 调用method通过.访问,就像struct里面访问字段一样
  • 定义在任何你自定义的类型、内置类型、struct等各种类型上面
  • 如果想要改变接受者的内容,可以使用指针

interface

简单的说,interface是一组method签名的组合,我们通过interface来定义对象的一组行为

/* 定义接口 */
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/* 定义结构体 */
type struct_name struct {
   /* variables */
}

/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
   /* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
   /* 方法实现*/
}

interface类型定义了一组方法,如果某个对象实现了某个接口的所有方法,则此对象就实现了此接口。

type Isay interface {
	say(word string) string
}

type dog struct {
	name string
}

type cat struct {
	sex string
}

func (d dog) say(word string) string {
	return d.name + word
}

func (c cat) say(word string) string {
	return "cat=" + word
}

//使用
var idg, icat Isay
idg = dog{"dog"}
fmt.Println(idg.say("hello"))
icat = cat{"0"}
fmt.Println(icat.say("world"))

最后,任意的类型都实现了空interface(我们这样定义:interface{}),也就是包含0个method的interface。

类型判断

Comma-ok断言

Go语言里面有一个语法,可以直接判断是否是该类型的变量: value, ok = element.(T),这里value就是变量的值,ok是一个bool类型,element是interface变量,T是断言的类型。

如果element里面确实存储了T类型的数值,那么ok返回true,否则返回false。

package main

import (
	"fmt"
	"strconv"
)

type Element interface{}
type List [] Element

type Person struct {
	name string
	age int
}

//定义了String方法,实现了fmt.Stringer
func (p Person) String() string {
	return "(name: " + p.name + " - age: "+strconv.Itoa(p.age)+ " years)"
}

func main() {
	list := make(List, 3)
	list[0] = 1 // an int
	list[1] = "Hello" // a string
	list[2] = Person{"Dennis", 70}

	for index, element := range list {
		if value, ok := element.(int); ok {
			fmt.Printf("list[%d] is an int and its value is %d\n", index, value)
		} else if value, ok := element.(string); ok {
			fmt.Printf("list[%d] is a string and its value is %s\n", index, value)
		} else if value, ok := element.(Person); ok {
			fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)
		} else {
			fmt.Printf("list[%d] is of a different type\n", index)
		}
	}
}

if-else过多,可以使用switch代替

package main

import (
	"fmt"
	"strconv"
)

type Element interface{}
type List [] Element

type Person struct {
	name string
	age int
}

//打印
func (p Person) String() string {
	return "(name: " + p.name + " - age: "+strconv.Itoa(p.age)+ " years)"
}

func main() {
	list := make(List, 3)
	list[0] = 1 //an int
	list[1] = "Hello" //a string
	list[2] = Person{"Dennis", 70}

	for index, element := range list{
		switch value := element.(type) {
			case int:
				fmt.Printf("list[%d] is an int and its value is %d\n", index, value)
			case string:
				fmt.Printf("list[%d] is a string and its value is %s\n", index, value)
			case Person:
				fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)
			default:
				fmt.Println("list[%d] is of a different type", index)
		}
	}
}

这里有一点需要强调的是:element.(type)语法不能在switch外的任何逻辑里面使用,如果你要在switch外面判断一个类型就使用comma-ok

posted @   S&L·chuck  阅读(193)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示