在前面几篇博文中记录了Go中一些基础语法,接下来补充记录一下一些基础使用以及struct类型类型的使用:
基础补充
import导包
我们知道,导入一个包,我们只需要使用import "xxx"
即可,导入多个包我们可以使用:
import (
"package1",
"package2"
)
我们还可以这样:
import . "fmt"
接下来,我们就可以不适用包名来调用函数了,如下:
package main
import . "fmt"
func main(){
Println("import . fmt的使用")
}
执行程序将会打印如下内容:
import . fmt的使用
我们还可以为包起个别名,如下:
import io "fmt"
如此,我们就为fmt包起了个别名叫做io。起别名的作用是什么呢?有可能我们会遇到两个名字一模一样的包,但是功能不一样,我们都需要使用,此时,我们就可以为其起一个别名来进行区分!
我们知道,当我们导入一个包时,就必须使用这个包,如果未曾使用它,那么将会发生变异错误!此时,我们可以使用_
,来进行忽略它:
import _ "fmt"
有人会想,这样写有什么用,你直接删除不就行了,何必这样大费周章!其实,这样写法,除了可以忽略这个包,但是它还会执行这个包的init函数,当有需要只需要执行它的init函数时,你就可以使用这种写法!
init函数
Go里面有两个保留的函数:init函数和main函数。这两个函数不能有任何的参数和返回值。每个包可以包含任意多个init函数,这些函数都会在程序执行开始的时候被调用。所有被编译器发现的init函数都会安排在main函数之前执行。假设有这样一个目录结构:
|Demo
|--models/
|----model.go
|--main.go
model.go
代码如下:
package models
import "fmt"
func init(){
fmt.Println("models-model中的init函数")
}
func init(){
fmt.Println("models-model中的init函数-2")
}
func Sum(a, b int) (result int) {
result = a + b
return
}
main.go
代码如下:
package main
import (
"Demo/models",
"fmt"
)
func init(){
fmt.Println("这是main中的init函数")
}
func main(){
result := models.Sum(10, 20)
fmt.Println(result)
}
接下来,我们运行一下main.go
文件,将会打印如下信息:
models-model中的init函数
models-model中的init函数-2
这是main中的init函数
30
首先,程序会先去找了import
里面中导入包中去寻找init
函数,然后依次执行,然后执行当前main
包中的init
函数,最后执行main
函数的内容!
new函数
表达式new(T)
将创建一个T类型的匿名变量,所做的是为T类型的新值分配并清零一块内存空间,然后将这块内存空间的地址作为结果返回,而这个结果就是指向这个新的T类型值的指针值,返回的指针类型为*T:
package main
import "fmt"
func main() {
var a1 *int
a1 = new(int)
fmt.Println(*a1)
a2 := new(int)
*a2 = 20
fmt.Println(*a2)
}
// 打印结果如下
0
20
我们还可以这样来使用:
package main
import "fmt"
func main() {
var a1 = 20
a2 := new(int)
a2 = &a1
*a2 = 18
fmt.Println(a1, *a2) // 20 20
}
我们只需要使用new()
函数,无需担心其内存的生命周期或怎么样将其删除,因为Go语言的内存管理系统会帮我们打理一切!
struct类型
Go语言中,也和C或者其他语言一样,我们可以声明新的类型,作为其他类型的属性或字段的容器。例如,我们可以创建一个自定义类型Student
来代表一个学生的实体。这个实体拥有属性:名称、年龄和地址信息。这样的类型我们称之为struct
,如下代码所示:
type Student struct{
name string
age int
addr string
}
接下来,我们来进行使用它:
var s Student
s.name = "laozhang"
s.age = 18
s.addr = "广东深圳"
fmt.Println(s)
// 打印结果如下
{laozhang 18 广东深圳}
除了上面这种声明使用之外,struct
类型还有几种声明使用方式:
- 按照顺序提供初始值
s := Student{"laozhang", 18, "广东深圳"}
- 根据
field:value
方式初始化,这样可以任意顺序
s := Student{age: 18, name: "laozhang", addr: "广东深圳"}
- 当然,也可以通过
new
函数来分配一个指针,下面的s为指针类型
s := new(Student)
s.name = "laozhang"
s.age = 18
s.addr = "广东深圳"
fmt.Println(*s)
// 打印结果如下
{laozhang 18 广东}
值得注意的是,按照顺序提供初始值,需要多有struct
下的所有属性进行赋值,否则将会报错,其他方式不需要,未进行赋值的属性将默认会是零值!
值得注意的是,如果struct
类型作为形参传递给另外一个函数,并在该函数修改struct
类型的内容,原struct
类型的值是不会发生改变的,如下:
package main
import "fmt"
type Student struct{
name string
age int
addr string
}
func modify(s Student){
s.age = 20
}
func main(){
s := Student{"laozhang", 10, "广东深圳"}
modify(s)
fmt.Println(s)
}
// 打印结果如下
{laozhang 10 广东深圳}
观察结果发现,源struct
类型的值并未发生改变。如果你有这样一个需求,需要在其他函数改变它的值,并使源struct
类型生效,你可以传递一个指针,如下:
package main
import "fmt"
type Student struct{
name string
age int
addr string
}
func modify(s *Student){
s.age = 20
// 或者使用下面这种写法,效果都是一样的
// (*s).age = 20
}
func main(){
s := Student{"laozhang", 18, "广东深圳"}
modify(&s)
fmt.Println(s)
}
struct匿名字段
实际上Go还支持只写类型,不写字段名称的方式,也就是匿名字段,也称为嵌入字段。当匿名字段是一个struct
类型时,那么这个struct
所拥有的所有字段都被隐式的引入了当前定义的这个struct
。举个栗子:
package main
import "fmt"
type People struct{
name string
age int
addr string
}
type Student struct{
People
score int
}
func main(){
var s Student
s.name = "laozhang"
s.age = 18
s.addr = "广东深圳"
s.score = 98
fmt.Println(s)
}
// 打印结果如下
{{laozhang 18 广东深圳} 98}
包含匿名字段的struct
类型,也可以使用上面初始化方式,如下:
- 按顺序提供初始值
s := Student{People{"laozhang", 18, "广东深圳"}, 98}
- 根据
field:value
方式初始化,这样可以任意顺序
s := Student{People: People{"laozhang", 18, "广东深圳"}, score: 98}
- 当然,也可以通过
new
函数来分配一个指针,下面的s为指针类型
s := new(Student)
s.name = "laozhang"
s.age = 18
s.addr = "广东深圳"
s.score = 98
fmt.Println(*s)
// 打印结果如下
{{laozhang 18 广东深圳} 98}
值得注意的是,如果当包含匿名字段时,本身字段名称与匿名字段中的属性名称有相同时,我们再进行.
语法赋值时,只会给当前的struct
类型的属性进行赋值,如下:
package main
import "fmt"
type People struct{
name string
age int
addr string
}
type Student struct{
People
name string
}
func main(){
var s Student
s.name = "laozhang"
s.age = 18
s.addr = "广东深圳"
fmt.Println(s)
}
// 打印结果如下
{{ 18 广东深圳} laozhang}
观察结果可以得知,匿名字段中的name属性并未成功赋值,而是给予的是一个零值。那么要如何才能给这种字段名称相同的情况下赋值呢,我们可以这样:
var s Student
s.People.name = "laozhang"
s.age = 18
s.addr = "广东深圳"
s.name = "laowang"
又或者这样:
var s Student
s.People = People{"laozhang", 18, "广东深圳"}
s.name = "laowang"
至此,Over~~~~