Golang int函数使用实例全面教程

 更新时间:2023年10月19日 11:04:29   作者:帽儿山的枪手  
这篇文章主要为大家介绍了Golang int函数使用实例全面教程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

init 函数

例如某些场景下,我们需要提前初始化一些变量或逻辑代码。在这种情况下,我们可以用一个特殊的init初始化函数来简化初始化工作,每个文件都可以包含一个或多个init初始化函数。

func init() {} // init()函数语法

init初始化函数除了不能被调用或引用外,其他行为和普通函数类似。在每个文件中的init初始化函数,在程序开始执行时按照它们声明的顺序被自动调用。

init函数先于main函数执行

注意:每个包在解决依赖的前提下,以导入声明的顺序初始化,每个包只会被初始化一次。因此,如果一个p包导入了q包,那么在p包初始化的时候可以认为q包必然已经初始化过了。

init函数的特征

  • init函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等
  • init函数没有输入参数、返回值
  • 每个包可以拥有多个init函数
  • 包的每个源文件也可以拥有多个init函数
  • 同一个包中多个init函数的执行顺序go语言没有明确的定义(说明)
  • 不同包的init函数按照包导入的依赖关系决定该初始化函数的执行顺序
  • init函数不能被其他函数调用,而是在main函数执行之前,自动被调用

初始化的过程

  • 初始化导入的包(顺序并不是按导入顺序(从上到下)执行的,runtime需要解析包依赖关系,没有依赖的包最先初始化);
  • 初始化包作用域的变量(并非按照“从上到下、从左到右”的顺序,runtime解析变量依赖关系,没有依赖的变量最先初始化);
  • 执行包的init函数;

runtime是go语言运行所需要的基础设施,也是go的核心特性。 该内容将放到后续《go基础之特性》章节为大家分享。

使用案例:init初始化顺序

package main
import "fmt"
var Num int = Call() // 全局变量声明
func init() { // 初始化函数
    fmt.Println("init()")
}
func Call() int {
    fmt.Println("Call()")
    return 1
}
func main() {
    fmt.Println("main()")
}

输出

Call()
init()
main()

结论,初始化的过程:

Num变量初始化 -> init() -> main()

案例:同一个包不同源码的init初始化顺序

首先创建3个文件, main.go代码中包含全局变量、init初始化函数定义,和main函数入口; a.go 和 b.go代码文件中,只包含全局变量、init初始化函数的定义。

main.go文件

package main
import (
    "fmt"
)
var _ int = m()
func init() {
   fmt.Println("init in main.go")
}
func m() int {
   fmt.Println("call m() in main.go")
   return 1
}
func main() {
   fmt.Println("main()")
}

a.go 文件

package main
import "fmt"
var _ int = a()
func init() {
   fmt.Println("init in a.go")
}
func a() int {
   fmt.Println("call a() in a.go")
   return 1
}

b.go 文件

package main
import "fmt"
var _ int = b()
func init() {
   fmt.Println("init in b.go")
}
func b() int {
   fmt.Println("call b() in b.go")
   return 1
}

 因为a.go 和 b.go 都归属于main包,但没有两文件中没有main函数入口。 在执行的时候,需要使用 go run main.go a.go b.go 这样形式执行,runtime会将所有文件进行加载初始化。

输出

call m() in main.go
call a() in a.go
call b() in b.go
init in main.go
init in a.go
init in b.go
main()

结论,同一个包不同源文件的init函数执行顺序,golang 没做官方说明。这块加载过程是按照 go run 文件排序。

使用案例:多个init函数初始化顺序

package main
import "fmt"
func init() {
   fmt.Println("init 1")
}
func init() {
   fmt.Println("init 2")
}
func main() {
   fmt.Println("main")
}

输出

init 1
init 2
main

结论:init函数比较特殊,可以在包里被多次定义。

方法

Golang中方法,实现是以绑定对象实例, 并隐式将实例作为第一实参 (receiver)。

定义说明

  • 只能为当前包内命名类型定义方法;
  • 参数 receiver 可任意命名,如方法中未曾使用,可省略参数名;
  • 参数 receiver 类型可以是 T 或 *T, 基类型 T 不能是接口或指针;
  • 不支持方法重载, receiver 只是参数签名的组成部分;
  • 可用实例 value 或 pointer 调用全部方法, 编译器自动转换

一个方法就是一个包含了接受者的函数, 接受者可以是命名类型或者结构体类型的一个值或者是一个指针。

方法定义

func (recevier type) methodName(参数列表) (返回值列表) {} // 参数和返回值可以省略

使用

定义一个结构类型和该类型的一个方法

package main
import "fmt"
// 结构体
type Info struct {
    Name  string
    Desc string
}
// 方法
func (u Info) Output() {
    fmt.Printf("%v: %v \n", u.Name, u.Desc)
}
func main() {
    // 值类型调用方法
    u1 := Info{"帽儿山的枪手", "分享技术文章"}
    u1.Output()
    // 指针类型调用方法
    u2 := Info{"帽儿山的枪手", "分享技术文章"}
    u3 := &u2
    u3.Output()
}

输出

帽儿山的枪手: 分享技术文章 
帽儿山的枪手: 分享技术文章

匿名方法

如类型S包含匿名字段 *T ,则 S 和 *S 方法集包含 T + *T 方法。

这条规则说的是当我们嵌入一个类型的指针, 嵌入类型的接受者为值类型或指针类型的方法将被提升, 可以被外部类型的值或者指针调用。

package main
import "fmt"
type S struct {
    T
}
type T struct {
    int
}
func (t T) testT() {
    fmt.Println("如类型 S 包含匿名类型 *T, 则 S 和 *S 方法集包含 T 方法")
}
func (t *T) testP() {
    fmt.Println("如类型 S 包含匿名字段 *T, 则 S 和 *S 方法集合包含 *T 方法")
}
func main() {
    s1 := S{T{1}}
    s2 := &s1
    fmt.Printf("s1 is : %v\n", s1)
    s1.testT()
    s1.testP() // 提升指针类型调用
    fmt.Printf("s2 is : %v\n", s2)
    s2.testT() // 提升值类型调用
    s2.testP()
}

输出

s1 is : {{1}}
如类型 S 包含匿名类型 *T, 则 S 和 *S 方法集包含 T 方法
如类型 S 包含匿名字段 *T, 则 S 和 *S 方法集合包含 *T 方法
s2 is : &{{1}}
如类型 S 包含匿名类型 *T, 则 S 和 *S 方法集包含 T 方法
如类型 S 包含匿名字段 *T, 则 S 和 *S 方法集合包含 *T 方法

表达式

根据调用者不同,方法分为两种表现形式

instance.method(args...) ---> <type>.func(instance, args...)

前者称为 method value, 后者 method expression则须显式传参。

package main
import "fmt"
type User struct {
    id   int
    name string
}
func (self *User) Test() {
    fmt.Printf("%p, %v\n", self, self)
}
func main() {
    u := User{1, "帽儿山的枪手"}
    u.Test()
    mValue := u.Test
    mValue() // 隐式传递 receiver
    mExpression := (*User).Test
    mExpression(&u) // 显式传递 receiver
}

输出

0xc00000c018, &{1 帽儿山的枪手}
0xc00000c018, &{1 帽儿山的枪手}
0xc00000c018, &{1 帽儿山的枪手}

结论,方法是指针类型,method value 会复制 receiver。

以上就是Golang int函数使用实例全面教程的详细内容,更多关于Golang int函数教程的资料请关注脚本之家其它相关文章!

相关文章

  • Golang根据job数量动态控制每秒协程的最大创建数量方法详解

    Golang根据job数量动态控制每秒协程的最大创建数量方法详解

    这篇文章主要介绍了Golang根据job数量动态控制每秒协程的最大创建数量方法
    2024-01-01
  • Golang中字符串(string)与字节数组([]byte)一行代码互转实例

    Golang中字符串(string)与字节数组([]byte)一行代码互转实例

    golang语言本身就是c的工具集,开发c的程序用到的大部分结构体,内存管理,携程等,golang基本都有,下面这篇文章主要给大家介绍了关于Golang中字符串(string)与字节数组([]byte)一行代码互转的相关资料,需要的朋友可以参考下
    2022-09-09
  • Golang搭建HTTP服务器

    Golang搭建HTTP服务器

    Golang是一种非常流行的编程语言,它的开发速度快,代码运行效率高等特点非常适合做Web应用的开发。本文将介绍如何使用Golang搭建HTTP服务器,需要的朋友可以参考阅读
    2023-04-04
  • Golang的第一个程序-Hello World

    Golang的第一个程序-Hello World

    这篇文章主要介绍了第一个Go程序-Hello World,在编写第一个go程序之前,我们要将系统的环境变量配好,下面来看具体的编一过程吧,需要的小伙伴可以参考一下
    2022-01-01
  • Systemd集成Golang二进制程序的方法

    Systemd集成Golang二进制程序的方法

    这篇文章主要介绍了Systemd集成Golang二进制程序的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-10-10
  • 深度解析Go语言中的未使用导入和变量

    深度解析Go语言中的未使用导入和变量

    本文解析Go语言中未使用导入和变量的处理机制,强调其强制使用规则对代码质量的保障,通过移除冗余、使用空白标识符及工具清理,可提升代码可读性与性能
    2025-06-06
  • Golang 模块引入及表格读写业务快速实现示例

    Golang 模块引入及表格读写业务快速实现示例

    这篇文章主要为大家介绍了Golang模块引入及表格读写业务的快速实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • Go语言集成开发环境之VS Code安装使用

    Go语言集成开发环境之VS Code安装使用

    VS Code是微软开源的一款编辑器,插件系统十分的丰富,下面介绍如何用VS Code搭建go语言开发环境,需要的朋友可以参考下
    2021-10-10
  • 使用gopacket解析协议层中的相关数据方式

    使用gopacket解析协议层中的相关数据方式

    文章介绍使用Wireshark抓取ping数据包并保存为pcap格式,通过Go语言gopacket解析,提取IP版本号、指定标识的数据包长度及应用层ICMP字符串内容,展示TCP/IP协议族解析的简便方法
    2025-07-07
  • Golang中漏洞数据库的使用详解

    Golang中漏洞数据库的使用详解

    govulncheck是Golang中的漏洞扫描工具,它强大功能的背后,离不开 Go 漏洞数据库(Go vulnerability database)的支持,所以本文就来为大家详细讲解下 Go 漏洞数据库相关的知识
    2023-09-09

最新评论