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之tcp自动重连实现方法

    golang之tcp自动重连实现方法

    下面小编就为大家带来一篇golang之tcp自动重连实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • 深入学习Golang并发编程必备利器之sync.Cond类型

    深入学习Golang并发编程必备利器之sync.Cond类型

    Go 语言的 sync 包提供了一系列同步原语,其中 sync.Cond 就是其中之一。本文将深入探讨 sync.Cond 的实现原理和使用方法,帮助大家更好地理解和应用 sync.Cond,需要的可以参考一下
    2023-05-05
  • Go条件控制语句详解(if-else、switch和select)

    Go条件控制语句详解(if-else、switch和select)

    条件语句用于检查一个条件是否为真,并根据条件的真假来决定是否执行相应的代码,下面这篇文章主要给大家介绍了关于Go条件控制语句(if-else、switch和select)的相关资料,需要的朋友可以参考下
    2024-03-03
  • golang下的viper包的简单使用方式

    golang下的viper包的简单使用方式

    这篇文章主要介绍了golang下的viper包的简单使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • golang实现文件上传并转存数据库功能

    golang实现文件上传并转存数据库功能

    这篇文章主要为大家详细介绍了golang实现文件上传并转存数据库功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • Go语言中Struct与继承与匿名字段和内嵌结构体全面详解

    Go语言中Struct与继承与匿名字段和内嵌结构体全面详解

    这篇文章主要介绍了Go语言中Struct与继承与匿名字段和内嵌结构体,Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性,感兴趣的可以了解一下
    2023-04-04
  • 解决Goland 提示 Unresolved reference 错误的问题

    解决Goland 提示 Unresolved reference 错误的问题

    这篇文章主要介绍了解决Goland 提示 Unresolved reference 错误的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Golang中Gin框架的使用入门教程

    Golang中Gin框架的使用入门教程

    这篇文章主要为大家详细介绍了Golang中Gin框架的使用教程,文中通过简单的示例为大家讲解了Gin框架的安装与使用,感兴趣的小伙伴开业跟随小编一起学习一下
    2022-10-10
  • 浅析golang开发Error的使用详解

    浅析golang开发Error的使用详解

    Error是Go语言开发中最基础也是最重要的部分,很多朋友不明白goland error的一些基本使用方法,今天通过本文给大家详细介绍下,需要的朋友参考下吧
    2021-07-07
  • Go语言编程中对文件读写的基本方法整理

    Go语言编程中对文件读写的基本方法整理

    这篇文章主要介绍了Go语言编程中对文件读写的基本方法整理,是Go语言入门学习中的基础知识,需要的朋友可以参考下
    2015-10-10

最新评论