protobuf-go pragma.go 文件介绍

pragma.go 文件

文件位于: https://github.com/protocolbuffers/protobuf-go/blob/master/internal/pragma/pragma.go

该文件核心思想: 利用 Golang 语法机制,扩展 Golang 语言特性

目前,该文件提供以下 4 个功能:

功能 说明
NoUnkeyedLiterals 禁止非 {Key: Value} 方式,初始化结构体
DoNotImplement 禁止第三方扩展实现其接口
DoNotCompare 禁止结构体做比较运算
DoNotCopy 禁止结构体值拷贝

下面依次说明实现原理

NoUnkeyedLiterals

定义如下:

// NoUnkeyedLiterals can be embedded in a struct to prevent unkeyed literals.
type NoUnkeyedLiterals struct{
   }

使用例子如下(原理见注释):

package main

import (
    "fmt"
    "unsafe"
)

type NoUnkeyedLiterals struct{
   }

type A1 struct {
   
    _  NoUnkeyedLiterals // 不影响 A1 结构体大小
    F1 int
    F2 string
}

type A2 struct {
   
    F1 int
    F2 string
}

func TestNoUnkeyedLiterals() {
   
    _ = A1{
   F1: 1, F2: "2"}
    _ = A2{
   1, "2"}                                          // 如果 A2 增加字段,可能会导致这里的初始化列表错误,而不知
    _ = A1{
   1, "2"}                                          // error: too few values in struct literal of type A1compilerInvalidStructLit
    fmt.Println(unsafe.Sizeof(A1{
   }) == unsafe.Sizeof(A2{
   })) // true
}

func main() {
   
    TestNoUnkeyedLiterals()
}

DoNotImplement

定义如下:

// DoNotImplement can be embedded in an interface to prevent trivial
// implementations of the interface.
//
// This is useful to prevent unauthorized implementations of an interface
// so that it can be extended in the future for any protobuf language changes.
type DoNotImplement interface{
    ProtoInternal(DoNotImplement) }

这个接口定义要结合internal目录,达成DoNotImplement接口对外部包不可见

比如protobuf-go中的FileImports接口,除了protobuf-go自己,其他第 3 方是没办法实现FileImports接口的

看下面代码:

import "google.golang.org/protobuf/internal/pragma"

type doNotImplement pragma.DoNotImplement

// FileImports is a list of file imports.
type FileImports interface {
   
    // Len reports the number of files imported by this proto file.
    Len() int
    // Get returns the ith FileImport. It panics if out of bounds.
    Get(i int) FileImport

    doNotImplement
}

因为DoNotImplement 定义在internal目录下,对第 3 方不可见

FileImports又需要实现ProtoInternal(DoNotImplement)方法

因为第 3 方没有办法实现ProtoInternal(DoNotImplement),进而阻止了FileImports接口的第 3 方扩展实现

DoNotCompare

定义如下:

// DoNotCompare can be embedded in a struct to prevent comparability.
type DoNotCompare [0]func()
  • 用法和NoUnkeyedLiterals一样,内嵌到结构体内
  • 同样不占空间,不影响结构体大小(因为定义的是 0 长度数组)
  • 因为 func 类型不能比较大小,因此被内嵌的结构体也无法比较大小

例子略

DoNotCopy

定义如下:

// DoNotCopy can be embedded in a struct to help prevent shallow copies.
// This does not rely on a Go language feature, but rather a special case
// within the vet checker.
//
// See https://golang.org/issues/8005.
type DoNotCopy [0]sync.Mutex

例子如下:

package main

import (
	"fmt"
	"sync"
	"unsafe"
)

type DoNotCopy [0]sync.Mutex

type A1 struct {
   
	_  DoNotCopy // 不影响 A1 结构体大小
	F1 int
	F2 string
}

type A2 struct {
   
	F1 int
	F2 string
}

func TestDoNotCopy(a A1) {
     // line 22
	fmt.Println(unsafe.Sizeof(A1{
   }) == unsafe.Sizeof(A2{
   })) // true
}

var a = A1{
   }

func main() {
   
	TestDoNotCopy(a)  // line 29
}

执行go vet,会有提示:

./main.go:22:22: TestDoNotCopy passes lock by value: pragma.A1 contains sync.Mutex
./main.go:29:16: call of TestDoNotCopy copies lock value: pragma.A1 contains sync.Mutex

相关推荐

  1. protobuf-go pragma.go 文件介绍

    2024-01-27 07:18:04       51 阅读
  2. <span style='color:red;'>protobuf</span>

    protobuf

    2024-01-27 07:18:04      54 阅读
  3. protobufprotobuf 开发 (二)

    2024-01-27 07:18:04       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-27 07:18:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-27 07:18:04       100 阅读
  3. 在Django里面运行非项目文件

    2024-01-27 07:18:04       82 阅读
  4. Python语言-面向对象

    2024-01-27 07:18:04       91 阅读

热门阅读

  1. 【数据库】oracle常见语句

    2024-01-27 07:18:04       50 阅读
  2. 使用Python模拟梦幻的萤火虫纷飞效果

    2024-01-27 07:18:04       56 阅读
  3. Vite+Electron快速构建一个VUE3桌面应用(三)——打包

    2024-01-27 07:18:04       53 阅读
  4. SSL了解

    SSL了解

    2024-01-27 07:18:04      62 阅读
  5. Redis面试题33

    2024-01-27 07:18:04       55 阅读
  6. 笔记 | Clickhouse命令行查询

    2024-01-27 07:18:04       42 阅读
  7. log-01-日志组件之 Log4j 入门介绍

    2024-01-27 07:18:04       55 阅读
  8. js直接下载附件和通过blob数据类型下载文件

    2024-01-27 07:18:04       54 阅读
  9. windows 固定ip多了一个169.254.xx.xx的ip的问题

    2024-01-27 07:18:04       59 阅读
  10. 中间件与rabbitmq

    2024-01-27 07:18:04       61 阅读
  11. GitHub OAuth认证的Django应用

    2024-01-27 07:18:04       61 阅读
  12. C# MapPath

    2024-01-27 07:18:04       54 阅读
  13. 2024 CKA 题库 | 15、备份还原 etcd

    2024-01-27 07:18:04       66 阅读