golang中的类和接口

发布于:2024-05-17 ⋅ 阅读:(147) ⋅ 点赞:(0)

在 Go 语言中并没有类的概念,而是使用结构体来实现面向对象的特性。通过 type 关键字可以定义自定义类型,包括结构体类型。下面是一个简单的示例:

package main

import "fmt"

// 定义一个结构体类型
type Person struct {
    Name string
    Age  int
}

// 定义结构体方法,类似于类的成员方法
func (p Person) SayHello() {
    fmt.Printf("Hello, my name is %s and I'm %d years old.\n", p.Name, p.Age)
}

func main() {
    // 创建一个结构体对象
    person := Person{Name: "Alice", Age: 30}
    
    // 调用结构体方法
    person.SayHello()
}

在这个示例中,我们使用 type 关键字定义了一个名为 Person 的结构体类型,它包含了 NameAge 两个字段。然后,我们定义了一个结构体方法 SayHello(),它用于输出该结构体对象的信息。在 main() 函数中,我们创建了一个 Person 类型的对象,并调用了 SayHello() 方法。

尽管 Go 中没有类的概念,但结构体类型可以包含字段和方法,从而实现面向对象编程的特性。结构体的方法可以在函数名前加上接收者参数,通过这种方式,结构体类型可以拥有类似于类的方法。

面向过程到面向对象

pulsar 生产者

下面是一个结构化的生产者方法

// 生产者
func Producer(ip string, port int8, topic string)  {
	client, err := pulsar.NewClient(pulsar.ClientOptions{
		URL: "pulsar://192.168.1.10:6650",
	})
	
	defer client.Close()
	
	producer, err := client.CreateProducer(pulsar.ProducerOptions{
		Topic: "demo123567",
	})

	
	for{
		_, err = producer.Send(context.Background(), &pulsar.ProducerMessage{
			Payload: []byte("hello"),
		})
		
		defer producer.Close()
		
		if err != nil {
			fmt.Println("Failed to publish message", err)
		} else {
			fmt.Println("Published message")
		}
		time.Sleep(1 * time.Second)
	}
}

改造成面向对象的结构体方法为:

package pulsartools

import (
	"context"
	"fmt"

	"github.com/apache/pulsar-client-go/pulsar"
)

// Producer 结构体定义
type Producer struct {
	client   pulsar.Client
	producer pulsar.Producer
}

// NewProducer 初始化生产者对象
func NewProducer(ip string, port int, topic string) (*Producer, error) {
	client, err := pulsar.NewClient(pulsar.ClientOptions{
		URL: fmt.Sprintf("pulsar://%s:%d", ip, port),
	})
	if err != nil {
		return nil, err
	}

	producer, err := client.CreateProducer(pulsar.ProducerOptions{
		Topic: topic,
	})
	if err != nil {
		return nil, err
	}

	return &Producer{
		client:   client,
		producer: producer,
	}, nil
}

// Send 发送消息
func (p *Producer) Send(msg string) error {
	_, err := p.producer.Send(context.Background(), &pulsar.ProducerMessage{
		Payload: []byte(msg),
	})
	if err != nil {
		fmt.Println("Failed to publish message", err)
	} else {
		fmt.Println("Published message")
	}
	return err
}

// Close 关闭生产者
func (p *Producer) Close() {
	p.producer.Close()
	p.client.Close()
}

这段代码将原来的生产者函数改造为了一个名为 Producer 的结构体类型,并定义了三个方法:NewProducerSendClose

  • NewProducer 方法用于初始化生产者对象。它接收 IP 地址、端口和主题作为参数,创建一个 Pulsar 客户端,并使用客户端创建一个生产者对象。如果初始化过程中出现错误,则返回 nil 和错误信息。

  • Send 方法用于发送消息。它接收一个消息字符串作为参数,并通过生产者对象发送消息到指定的主题。如果发送过程中出现错误,则输出错误信息;否则输出消息发送成功的提示。

  • Close 方法用于关闭生产者对象。它先关闭生产者,然后关闭 Pulsar 客户端。

这样改造后,生产者的功能被封装在了一个结构体类型中,使得代码更加模块化和可维护。通过调用结构体的方法来使用生产者对象,使得代码更加直观和易于理解。

接口

在 Go 语言中,接口是一种抽象类型,它定义了对象的行为。接口类型是由一组方法定义的集合,一个对象只要实现了接口中定义的所有方法,就被认为是实现了该接口。

接口的定义使用 type 关键字,接口中的方法没有实现,只有方法签名,类似于其他语言中的抽象方法。任何类型只要拥有接口中定义的全部方法,即使未显式声明实现了该接口,也被视为实现了该接口。

接口的声明格式为

type InterfaceName interface {
    Method1() ReturnType1
    Method2(arg Type) ReturnType2
    // 更多方法...
}

其中 InterfaceName 是接口的名称,Method1Method2 等是接口的方法,ReturnType1ReturnType2 是方法的返回类型,Type 是方法参数的类型。
下面是一个简单的接口示例

package main
import "fmt"
// 定义一个接口
type Animal interface {
    Speak() string
}
// 定义一个结构体类型
type Dog struct{}
// Dog 结构体类型实现了 Animal 接口的 Speak 方法
func (d Dog) Speak() string {
    return "Woof!"
}
// main 函数
func main() {
    // 创建一个 Dog 对象
    dog := Dog{}
    // 将 Dog 对象赋值给 Animal 接口
    var animal Animal = dog
    // 调用接口方法
    fmt.Println(animal.Speak()) // Output
Woof!
}

在这个示例中,我们定义了一个 Animal 接口,它包含一个 Speak 方法。然后我们定义了一个 Dog 结构体类型,并为它实现了 Speak 方法。在 main 函数中,我们创建了一个 Dog 对象,并将其赋值给 Animal 接口。通过接口,我们可以调用 Speak 方法来执行相应的行为。

接口的使用使得代码更加灵活和可扩展,可以让不同的类型通过实现相同的接口来实现多态。


网站公告

今日签到

点亮在社区的每一天
去签到