Skip to content

接口

接口:是一组行为的抽象,尽量用接口,以实现面向接口编程

当一个类型实现了接口中所有方法,就视为实现了该接口,无需显式声明

package main
import "fmt"
type Payment interface {
// Pay 支付
Pay(amount float64) (string, error)
// Refund 退款
Refund(transactionID string, amount float64) (string, error)
// Query 查询
Query(transactionID string) (string, error)
}
type Alipay struct {
AppID string
}
func (a *Alipay) Pay(amount float64) (string, error) {
return fmt.Sprintf("pay %f with alipay\n", amount), nil
}
func (a *Alipay) Refund(transactionID string, amount float64) (string, error) {
return fmt.Sprintf("refund %s with alipay\n", transactionID), nil
}
func (a *Alipay) Query(transactionID string) (string, error) {
return fmt.Sprintf("query %s with alipay\n", transactionID), nil
}
type Wechatpay struct {
AppID string
}
func (w *Wechatpay) Pay(amount float64) (string, error) {
return fmt.Sprintf("pay %f with wechatpay\n", amount), nil
}
func (w *Wechatpay) Refund(transactionID string, amount float64) (string, error) {
return fmt.Sprintf("refund %s with wechatpay\n", transactionID), nil
}
func (w *Wechatpay) Query(transactionID string) (string, error) {
return fmt.Sprintf("query %s with wechatpay\n", transactionID), nil
}
// 抽象: 多态的体现
func ProcessPayment(p Payment, amount float64) (string, error) {
fmt.Println("开始处理支付请求...")
payStr, err := p.Pay(amount)
if err != nil {
return "", err
}
fmt.Printf("支付成功,交易金额为: %s", payStr)
return payStr, nil
}
func main() {
alipay := &Alipay{
AppID: "123",
}
wechatpay := &Wechatpay{
AppID: "456",
}
transcations := []struct {
Payment Payment
Amount float64
Name string
}{
{alipay, 100, "alipay"},
{wechatpay, 100, "wechatpay"},
}
for _, transcation := range transcations {
payStr, err := ProcessPayment(transcation.Payment, transcation.Amount)
if err != nil {
fmt.Printf("支付失败,错误信息为: %s\n", err.Error())
continue
}
fmt.Printf("ProcessPayment 支付成功,交易编号为: %s\n", payStr)
}
}
package main
import (
"encoding/json"
"io"
"net/http"
)
// 定义接口
// 语法:type name interface{}
type Server interface {
Route(pattern string, handlerFunc http.HandlerFunc)
Start(address string) error
}
// 结构体如何实现接口
// 当一个结构体具备接口的所有的方法的时候,它就实现了这个接口
type sdkHttpServer struct {
Name string
}
// Route 注册路由
func (s *sdkHttpServer) Route(pattern string, handlerFunc http.HandlerFunc) {
http.HandleFunc(pattern, handlerFunc)
}
// Start 启动服务
func (s *sdkHttpServer) Start(address string) error {
return http.ListenAndServe(address, nil)
}
func NewHttpServer(name string) Server {
return &sdkHttpServer{
Name: name,
}
}
// sync context 抽象
// TODO 思考:这里为什么不选择interface,而选择struct
type Context struct {
Write http.ResponseWriter
request *http.Request
}
func (c *Context) ReadJson(data interface{}) error {
// 读取data
body, err := io.ReadAll(c.request.Body)
if err != nil {
// 要返回掉,不然会继续执行后面的代码
return err
}
// 反序列化
err = json.Unmarshal(body, data)
if err != nil {
return err
}
return nil
}
func (c *Context) WriteJson(code int, data interface{}) error {
c.Write.WriteHeader(code)
respJson, err := json.Marshal(data)
if err != nil {
return err
}
_, err = c.Write.Write(respJson)
return err
}
func (c *Context) SuccessJson(data interface{}) error {
return c.WriteJson(http.StatusOK, data)
}
func (c *Context) BadRequestJson(data interface{}) error {
return c.WriteJson(http.StatusBadRequest, data)
}
func (c *Context) ServerErrorJson(data interface{}) error {
return c.WriteJson(http.StatusInternalServerError, data)
}
func home(writer http.ResponseWriter, request *http.Request) {
ctx := &Context{
Write: writer,
request: request,
}
err := ctx.ReadJson(request)
if err != nil {
// TODO
return
}
err = ctx.WriteJson(http.StatusOK, map[string]interface{}{
"code": 200,
"message": "success",
"data": request.URL.Path,
})
if err != nil {
// TODO 写入日志
}
}
func main() {
server := NewHttpServer("my-server")
server.Route("/", home)
server.Start(":8080")
}

空接口interface{}不包含任何方法,可以存储任意类型的值,类似于TypeScript中的any

package main
import "fmt"
func processEmptyInterface(i interface{}) {
// 类型断言
switch v := i.(type) {
case int:
fmt.Println("int", v)
case string:
str := i.(string)
fmt.Println("string", str)
default:
fmt.Println("unknown", v)
}
}
func main() {
var anything interface{}
processEmptyInterface(anything) // unknown <nil>
anything = 123
processEmptyInterface(anything) // int 123
anything = "hello"
processEmptyInterface(anything) // string hello
}
package main
import (
"fmt"
"time"
)
type BaseUser struct {
ID int
UserName string
Email string
CreatedAt time.Time
}
func (b BaseUser) GetCreateDate() string {
return b.CreatedAt.Format(time.DateTime)
}
func (b BaseUser) DisplayBasicInfo() {
fmt.Printf("用户ID: %d, 用户名: %s, 邮箱: %s, 创建时间: %s\n", b.ID, b.UserName, b.Email, b.GetCreateDate())
}
type Address struct {
Province string
City string
Street string
Detail string
}
func (a Address) GetFullAddress() string {
return fmt.Sprintf("%s,%s,%s,%s\n", a.Province, a.City, a.Street, a.Detail)
}
type NormalUser struct {
BaseUser
Address []Address
}
func (nu *NormalUser) AddAddress(address Address) {
nu.Address = append(nu.Address, address)
}
type VipUser struct {
BaseUser
Address []Address
VipLevel int
Discount float64
ExpireDate time.Time
}
func (v VipUser) IsValid() bool {
return time.Now().Before(v.ExpireDate)
}
func (v VipUser) GetDiscount() float64 {
if v.IsValid() {
return v.Discount
}
return 1.0
}
type UserService struct {
}
const (
UserTypeNormal = "normal"
UserTypeVip = "vip"
)
func generateUserID() int {
return int(time.Now().Unix())
}
func (s *UserService) CreateUser(username, email, userType string) (user interface{}, err error) {
baseUser := BaseUser{
ID: generateUserID(),
UserName: username,
Email: email,
CreatedAt: time.Now(),
}
switch userType {
case UserTypeNormal:
normalUser := NormalUser{
BaseUser: baseUser,
Address: []Address{},
}
return normalUser, nil
case UserTypeVip:
vipUser := VipUser{
BaseUser: baseUser,
VipLevel: 1,
Discount: 0.9,
ExpireDate: time.Now().AddDate(0, 0, 30),
}
return vipUser, nil
default:
return nil, fmt.Errorf("invalid user type: %s", userType)
}
}
func main() {
userService := &UserService{}
normalUser, err := userService.CreateUser("张三", "zs@mail.com", UserTypeNormal)
if err != nil {
fmt.Println("创建普通用户失败,err: ", err)
return
}
nUser := normalUser.(NormalUser)
nUser.AddAddress(Address{
Province: "广东省",
City: "深圳市",
Street: "南山大道",
Detail: "深圳南山大道100号",
})
nUser.DisplayBasicInfo()
vipUser, err := userService.CreateUser("李四", "ls@mail.com", UserTypeVip)
if err != nil {
fmt.Println("创建VIP用户失败,err: ", err)
return
}
users := []interface{}{nUser, vipUser}
for _, user := range users {
switch u := user.(type) {
case NormalUser:
fmt.Println("普通用户ID:", u.ID)
fmt.Println("普通用户创建时间:", u.GetCreateDate())
fmt.Println("普通用户地址:")
for _, address := range u.Address {
fmt.Println("-", address.GetFullAddress())
}
case VipUser:
fmt.Println("VIP用户ID:", u.ID)
fmt.Println("VIP用户创建时间:", u.GetCreateDate())
fmt.Println("VIP用户等级:", u.VipLevel)
fmt.Println("VIP用户折扣:", u.GetDiscount())
fmt.Println("VIP用户状态:", u.IsValid())
}
}
}
package main
import "fmt"
/*
实现面向对象
1. 结构体代替类:使用结构体组织数据,方法通过接收者定义
2. 组合优于继承:通过结构体嵌入实现代码复用
3. 方法接收者:值接收者不修改原对象,指针接收者可以修改原对象
4. 接口实现多态:不同类型实现相同接口,提高代码灵活性
5. 方法提升:嵌入结构体的方法和字段会自动提升到外部结构体
*/
type Notifier interface {
Notify(message string) error
}
type EmailNotify struct {
SMTPHost string
SMTPPort int
}
func (e *EmailNotify) Notify(message string) error {
fmt.Printf("发送邮件通知:%s\n", message)
return nil
}
type SMSNotify struct {
Secret string
TmplString string
}
func (s *SMSNotify) Notify(message string) error {
fmt.Printf("发送短信通知:%s\n", message)
return nil
}
type BroadCastNotify struct {
notifiers []Notifier
}
func (b *BroadCastNotify) Notify(message string) error {
for _, n := range b.notifiers {
err := n.Notify(message)
if err != nil {
return err
}
}
return nil
}
type OrderService struct {
notifier Notifier
}
func (o *OrderService) SetNotifier(n Notifier) {
o.notifier = n
}
func (o *OrderService) CreateOrder(product string, quantity int) {
fmt.Printf("创建订单:%s, 数量:%d\n", product, quantity)
err := o.notifier.Notify("订单创建成功")
if err != nil {
fmt.Println("通知失败,err: ", err)
return
}
}
func main() {
orderService := &OrderService{}
emailNotify := &EmailNotify{
SMTPHost: "smtp.qq.com",
SMTPPort: 465,
}
smsNotify := &SMSNotify{
Secret: "ABCD1234",
TmplString: "您的订单已创建成功",
}
broadcastNotify := &BroadCastNotify{
notifiers: []Notifier{emailNotify, smsNotify},
}
orderService.SetNotifier(emailNotify)
orderService.CreateOrder("商品1", 1)
orderService.SetNotifier(smsNotify)
orderService.CreateOrder("商品2", 1)
orderService.SetNotifier(broadcastNotify)
orderService.CreateOrder("商品3", 1)
}