云海的博客
首页
  • 接口
  • 数组
  • slice
  • map
  • 指针
  • 反射
  • Context
  • sync.map
  • 锁
  • 类型和类型指针分析
  • recover
  • 从零实现RPC框架
  • make和new区别
  • channel
  • sync.Once
  • sync.Pool
  • protobuf
  • MongoDB pkg源码-findone
  • MyBatis
  • Maven
  • 解析Laravel框架—路由处理
  • PHP(客户端)与 Golang(服务端)使用grpc+protobuf 通信
  • JAVA(客户端)与 Golang(服务端) 使用grpc+protobuf通信
  • Docker使用笔记-常用命令
  • Docker使用笔记-容器间通讯
  • Docker使用笔记-搭建Redis集群
  • Docker使用笔记-镜像多阶段构建
  • Kubernetes部署golang服务
  • Linux常用命令
  • Docker安装Prometheus与Grafana
  • Protobuf
  • TCP抓包
  • 概述-《TCP/IP详解》读书笔记
  • 索引
  • 事务隔离级别
  • 常识
  • 每日一题(1)
  • 每日一题(2)
  • 每日一题(3)
  • 每日一题(4)
关于
GitHub (opens new window)

云海

服务端研发
首页
  • 接口
  • 数组
  • slice
  • map
  • 指针
  • 反射
  • Context
  • sync.map
  • 锁
  • 类型和类型指针分析
  • recover
  • 从零实现RPC框架
  • make和new区别
  • channel
  • sync.Once
  • sync.Pool
  • protobuf
  • MongoDB pkg源码-findone
  • MyBatis
  • Maven
  • 解析Laravel框架—路由处理
  • PHP(客户端)与 Golang(服务端)使用grpc+protobuf 通信
  • JAVA(客户端)与 Golang(服务端) 使用grpc+protobuf通信
  • Docker使用笔记-常用命令
  • Docker使用笔记-容器间通讯
  • Docker使用笔记-搭建Redis集群
  • Docker使用笔记-镜像多阶段构建
  • Kubernetes部署golang服务
  • Linux常用命令
  • Docker安装Prometheus与Grafana
  • Protobuf
  • TCP抓包
  • 概述-《TCP/IP详解》读书笔记
  • 索引
  • 事务隔离级别
  • 常识
  • 每日一题(1)
  • 每日一题(2)
  • 每日一题(3)
  • 每日一题(4)
关于
GitHub (opens new window)
  • 接口
  • 数组
  • slice
  • map
  • 反射
  • sync.Pool
  • net包笔记
  • net-rpc分析
  • 指针
  • 数组排序
  • Context
  • sync.map
  • 锁
  • recover
  • 泛型
    • 类型和类型指针分析
    • make和new区别
    • channel
    • sync.Once
    • protobuf
    • GoLand debug(1)
    • 从零实现RPC框架
    • 从零开始学Go Origin框架
    • MongoDB pkg源码-findone
    • Golang
    云海
    2022-07-16
    目录

    泛型

    # 概述

    如果我们想实现一个简单的tree数据结构,每个节点持有一个值。在Go 1.18之前,实现这种结构的典型方法如下:

    type Node struct{
      value interface{}
    }
    
    1
    2
    3

    这在大多少情况下,都很好用,但他也有一些缺点。 首先,interface{} 可以是任何东西,如果我们想限制value可能持有的类型,例如整数和浮点数,我们只能在运行时检查这个限制。

    func (n Node) IsValid() bool {
      switch n.value.(type) {
      case int, float32, float64:
          return true
      default:
          return false
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    这样并不可能在编译时限制类型,像上面这样的类型判断在许多Go库中都是很常见的做法。 第二,对Node中的值进行处理是非常繁琐和容易出错的。对值做任何事情都会涉及到某种类型的断言,即使你可以安全的假设值持有一个int值。

    num, ok := node.value.(int)
    if !ok {
    
    }
    double := number * 2
    
    1
    2
    3
    4
    5

    这些只是使用interface{}的一些不便之处,它既没有提供类型安全,并有可能导致难以恢复的运行时错误。

    # 解决方法

    我们不打算接受任意数据类型或数据类型,而是定义一个叫做T的占位符类型,作为值的类型。请注意,这段代码还不会通过编译。

    type Node(T) struct {
      value T
    }
    
    1
    2
    3

    首先需要声明泛型类型T,这是在结构或函数名称后面方括号里使用的。T 可以是任何类型,只有实例化一个具有明确类型的Node时,T才会被推导为该类型。

    n := Node[int] {
      value: 5,
    }
    
    1
    2
    3

    泛型Node被实例化为Nodeint,所以T是一个int。

    类型约束 上面的实现里,

    上次更新: 2023/01/11
    recover
    类型和类型指针分析

    ← recover 类型和类型指针分析→

    最近更新
    01
    函数
    04-11
    02
    面试题
    04-11
    03
    EFK日志收集系统单机版
    08-18
    更多文章>
    Theme by Vdoing | Copyright © 2022-2025 Evan Xu | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式