当前位置:网站首页>go基于泛型实现继承
go基于泛型实现继承
2022-08-08 20:53:00 【Chise1】
概述
在某些情况下,我们需要继承的时候父类的函数和方法能够影响(或使用)子类的一些数据,这并不符合一般情况下的类原则,但是很有用。
在go里面,我们通过组合实现继承,但是组合的类没办法操作同级别的类,解决方案是把操作方法提出来作为函数进行处理。
对于有些情况下,明明是紧密耦合的函数,却不得不拆出来单独使用,还是让人很不爽。
好在go的泛型能够解决这个问题。
下面是我基于go泛型实现的一个动态结构体,包含一些固定的基本字段以及一些动态字段。在某些需要直接从请求参数获取字段名并赋值的需求的时候,这个操作很有用。特别是一个结构体几十个字段的时候:
package models
import (
"encoding/json"
"reflect"
"regexp"
)
type Info[T any] struct {
T T //固定字段,对于一般情况下会本身会读取到的字段写入这里
Ext map[string]interface{
} // 其它扩展数据,根据需要添加,key/value形式获取
}
func NewInfo[T any]() Info[T] {
// 主要是为了初始化map
res := Info[T]{
}
res.Ext = map[string]interface{
}{
}
return res
}
func (s Info[T]) MarshalJSON() ([]byte, error) {
// 将动态字段和静态字段组合放到一个结构体
marshal, err := json.Marshal(s.T)
if err != nil {
return nil, err
}
if len(s.Ext) != 0 {
extMarshal, err := json.Marshal(s.Ext)
if err != nil {
return nil, err
}
marshal = append(marshal[0:len(marshal)-1], []byte(`,"__ext__":{},`)...)
marshal = append(marshal, extMarshal[1:]...)
}
return marshal, nil
}
func (s *Info[T]) UnmarshalJSON(data []byte) error {
// 反序列化
dataS := string(data)
subInfo := regexp.MustCompile(`,"__ext__":{},`).Split(dataS, 2)
if len(subInfo) == 1 {
//未找到对象
return json.Unmarshal(data, &s.T)
} else {
baseStr := subInfo[0] + "}"
extStr := "{" + subInfo[1]
err := json.Unmarshal([]byte(baseStr), &s.T)
if err != nil {
return err
}
ext := map[string]interface{
}{
}
err = json.Unmarshal([]byte(extStr), &ext)
if err != nil {
return err
}
s.Ext = ext
return nil
}
}
func (s Info[T]) GetAttr(fieldName string) (v interface{
}, find bool) {
// 根据字符串获取值,这里甚至可以改造为忽略大小写
refval := reflect.ValueOf(s)
val := refval.FieldByName(fieldName)
if val.IsValid() {
return val.Interface(), true
}
dynamicStruct, ok := s.Ext[fieldName]
return dynamicStruct, ok
}
func (s *Info[T]) SetAttr(fieldName string, value interface{
}) bool {
//根据字符串写入值,这里也可以忽略大小写
refval := reflect.ValueOf(s).Elem()
val := refval.FieldByName(fieldName)
if val.IsValid() {
val.Set(reflect.ValueOf(value))
return true
}
s.Ext[fieldName] = value
return false
}
边栏推荐
- 差点被ECCV错过的论文:视频理解新框架,仅用微调的「成本」,达到预训练的「全能」...
- C语言初阶-指针
- 如何用WebSocket打造Web端IM即时通讯聊天
- iMeta | 深圳先进院戴磊组开发可同时提取共存菌株的组成和基因成分谱的菌株分析工具...
- 编译原理——LL1分析程序实验(C#)
- The WPF main form calls User32's SetWindowPos to set the form to the top, which will cause the problem of grabbing the focus with other forms
- Everything原理探究以及C#实现
- 门外汉掌握数据分析处理技术的路线图
- Web3到底是什么?
- Questions about Mac terminal custom commands and Mysql command
猜你喜欢
随机推荐
【翻译】用Argo CD揭开企业规模的持续交付的秘密成分
源码分析Canal专栏
Kotlin parsing String path knowledge
Solve the problem of slow speed of gradle import package
Kotlin delegate property knowledge points
基于opencv的实时睡意检测系统
Bluu Seafood launches first lab-grown fish products
Redis Bloom Filter
并发和并行——从线程,线程池到任务
随手记:laravel、updateOrCreate 和 updateOrInsert 的区别
知乎高赞:如果一个程序员工作5年后还没成为大牛,是不是该考虑别的路子了?
第十三届蓝桥杯(Web 应用开发)线上模拟赛【第九题】(知乎首页数据动态化)
PyTorch入门(六):模型的训练套路
Web3到底是什么?
Factorial of 1088 N
单片机--IIC总线篇
Everything原理探究以及C#实现
学习笔记:线性表的顺序表示和实现(二级指针实现)
学习笔记:2.3 静态链表 循环链表 双向链表
Redis布隆过滤器