go程序中同一个包下为什么会存在多个同名的函数或变量(详细解析)

 更新时间:2024年05月21日 10:56:12   作者:ProblemTerminator  
这篇文章主要介绍了go程序中同一个包下为什么会存在多个同名的函数或变量(详细解析),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

背景

首先,这种情况显然是不符合编译规则的,我们都知道在同一个包下出现两个同名的函数、变量、常量等会编译不通过,那么怎么还会有这种现象存在?

如下,源码中任意找一个有这种现象的包:

一探究竟

既然都是go代码,肯定是适配同一套逻辑的。

创建一个测试项目,创建一个包pkg,分别创建如下文件:

我们让mypkg包下的所有文件中都有GetPackageName函数(返回的值不同)、flag变量。

注意,这些文件目前并未提示redeclared。

然后main中调用GetPackageName函数。

在运行之前,编译器并没有显式的报错。接着go build,编译正常。运行结果输出了:

mypkg from windows

交叉编译一下Linux平台,运行:

mypkg from linux

看起来编译时自动找到对应文件处理了。

继续。

在mypkg包下接着新建一个名为openbsd.go的文件,和上述文件的函数保持同名,然后很明显的报错出来了:'GetPackageName' redeclared in this package

条件不变,且在pkg_windows.go文件已存在的前提下:

继续创建名为_openbsd.go的文件,没有报错。

继续创建名为pkg_amd64.go、pkg_x64.go、pkg_x86.go、othername_amd64.go等文件均会提示redeclared。

但创建的othername_arm64.go、pkg_linux_amd64.go、pkg_linux_arm64.go不会提示。

对于linux的两个文件,这里看着没毛病,实际上在linux、amd64平台上编译就会报错:

mypkg\pkg_linux_amd64.go:4:2: flag redeclared in this block
        mypkg\pkg_linux.go:4:2: other declaration of flag 
mypkg\pkg_linux_amd64.go:7:6: GetPackageName redeclared in this block
        mypkg\pkg_linux.go:7:6: other declaration of GetPackageName

是因为pkg_linux_amd64.go文件和pkg_linux.go文件的同名内容冲突了,在linux、amd64平台上编译,这两文件就会被适配到。

如果目标平台改为linux、arm64进行编译,也会报:

mypkg\pkg_arm64.go:4:2: flag redeclared in this block
        mypkg\othername_arm64.go:4:2: other declaration of flag
mypkg\pkg_arm64.go:7:6: GetPackageName redeclared in this block
        mypkg\othername_arm64.go:7:6: other declaration of GetPackageName
mypkg\pkg_linux.go:4:2: flag redeclared in this block
        mypkg\othername_arm64.go:4:2: other declaration of flag
mypkg\pkg_linux.go:7:6: GetPackageName redeclared in this block
        mypkg\othername_arm64.go:7:6: other declaration of GetPackageName

是因为othername_arm64.go文件、pkg_arm64.go和pkg_linux.go文件的同名内容冲突了,在linux、arm64平台上编译,这三个文件就会被适配到。

综合来看:

1,类似约定xxx_windows.go、xxx_arm64.go、xxx_linux_arm64.go命名的文件用于实现平台特定的代码。

2,编译器自动认识以_系统/arch名称结尾的go文件。

3,编译时,GOOS 和 GOARCH都可以在文件名上来做构建约束,go编译器会根据当前操作系统自动选择匹配的文件进行编译。

增加构建约束 & 不同格式的构建约束

例如,针对不同的系统、架构的代码文件做相同的事情,我们可以进行编译约束:

即,顶部增加如下格式的约束(不能漏掉注释):

//go:build arm64 && freebsd

如下格式仅针对特定操作系统:

//go:build freebsd

如下格式针对特定的多个系统均可:

//go:build aix || darwin || freebsd || linux

如下格式的文件支持在linux系统、但不能在arm或arm64架构下进行编译

//go:build linux && !arm && !arm64

感叹号表示“非”。

以上是go 1.17及以上版本引入的格式,定义了一个布尔表达式,包含了逻辑运算符,条件可以更复杂。

与此不同,下面的格式是go 1.17以下支持的约束格式:

// +build freebsd

也会有两种格式并存的情况:

//go:build linux
// +build linux

因为也有环境是老编译器的情况,老版本的编译器不能识别新的约束语法。

go语言支持的系统和架构列表

#go tool dist list
aix/ppc64
android/386
android/amd64
android/arm
android/arm64
darwin/amd64
darwin/arm64
dragonfly/amd64
freebsd/386
freebsd/amd64
freebsd/arm
freebsd/arm64
freebsd/riscv64
illumos/amd64
ios/amd64
ios/arm64
js/wasm
linux/386
linux/amd64
linux/arm
linux/arm64
linux/loong64
linux/mips
linux/mips64
linux/mips64le
linux/mipsle
linux/ppc64
linux/ppc64le
linux/riscv64
linux/s390x
netbsd/386
netbsd/amd64
netbsd/arm
netbsd/arm64
openbsd/386
openbsd/amd64
openbsd/arm
openbsd/arm64
openbsd/ppc64
plan9/386
plan9/amd64
plan9/arm
solaris/amd64
wasip1/wasm
windows/386
windows/amd64
windows/arm
windows/arm64

到此这篇关于go程序中同一个包下为什么会存在多个同名的函数或变量的文章就介绍到这了,更多相关go程序同一个包存在多个同名的函数或变量内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go处理json数据方法详解(Marshal,UnMarshal)

    Go处理json数据方法详解(Marshal,UnMarshal)

    这篇文章主要介绍了Go处理json数据的方法详解,Marshal(),UnMarshal(),需要的朋友可以参考下
    2022-04-04
  • 详解golang RWMutex读写互斥锁源码分析

    详解golang RWMutex读写互斥锁源码分析

    这篇文章主要介绍了详解golang RWMutex读写互斥锁源码分析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • GO语言embed机制的使用

    GO语言embed机制的使用

    本文详细介绍了Go语言中使用embed机制将静态文件(如图片、文本和目录)嵌入到程序中,包括文件转[]byte、string类型,以及使用FS结构组合多个文件和目录的方法,下面就来详细的介绍一下
    2026-03-03
  • Golang实现短网址/短链服务的开发笔记分享

    Golang实现短网址/短链服务的开发笔记分享

    这篇文章主要为大家详细介绍了如何使用Golang实现短网址/短链服务,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-05-05
  • Go操作etcd的实现示例

    Go操作etcd的实现示例

    etcd是近几年比较火热的一个开源的、分布式的键值对数据存储系统,提供共享配置、服务的注册和发现,本文主要介绍etcd的安装和使用,感兴趣的可以了解一下
    2021-09-09
  • Go语言基础知识总结(语法、变量、数值类型、表达式、控制结构等)

    Go语言基础知识总结(语法、变量、数值类型、表达式、控制结构等)

    这篇文章主要介绍了Go语言基础知识总结(语法、变量、数值类型、表达式、控制结构等),本文汇总了Go语言的入门知识,需要的朋友可以参考下
    2014-10-10
  • 详解如何在Go中实现优雅停止

    详解如何在Go中实现优雅停止

    和其他语言相比,Go 中有相同也有不同,相同的是实现思路上和其他语言没啥差异,不同在于 Go 采用的是 goroutine + channel 的并发模型,与传统的进程线程相比,实现细节上存在差异,本文将从实际场景和它的一般实现方式展开,逐步讨论这个话题,需要的朋友可以参考下
    2024-04-04
  • go语言接口之接口值举例详解

    go语言接口之接口值举例详解

    接口是一种抽象类型,是对其他类型行为的概括与抽象,从语法角度来看,接口是一组方法定义的集合,下面这篇文章主要给大家介绍了关于go语言接口之接口值的相关资料,文章通过代码介绍的非常详细,需要的朋友可以参考下
    2024-06-06
  • golang并发锁使用详解

    golang并发锁使用详解

    这篇文章主要介绍了golang并发锁使用详解的相关资料,需要的朋友可以参考下
    2023-02-02
  • go build失败报方法undefined的解决过程

    go build失败报方法undefined的解决过程

    go build命令用于编译我们指定的源码文件或代码包以及它们的依赖包,下面这篇文章主要给大家介绍了关于go build失败报方法undefined的解决过程,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-11-11

最新评论