Golang初级系列教程-Struct
Go
是面向对象语言吗对于接受过面向对象思想的用户首先需要声明一点:Go
中没有 class
关键字。关键字 struct
是一个集大成者。Java
、C#
、C++
以及其它语言都支持 struct
。其中一些支持 struct
中包含方法。Go
也支持,而且提供更多的功能。
在一些面向对象语言中,方法是 class
或者 struct
中存在的,在 Go
中只有 struct
。
Java
部分代码
class House {
public String getHouseName() { //method defined within class
//implementation
}
}
Go
部分代码
type House struct { }
func (h House) GetHouseName() string { } //method defined outside of struct, but works on House
虽然在 Go
中没有面向对象的概念,但是通过 struct
的一些特性,类似的功能特性也是可以实现的。结构体通过关键字 type
和 struct
定义。
type my_struct_name struct { }
type Rectangle struct { }
type Vehicle struct { }
type Vehicle1_Car struct { }
上面的定义都符合 Go
变量定义的规则,都是有效的语句。下面几个则不正确。
type Hash# struct {} //cannot have special characters
type 0struct struct {} //cannot start with a number
另外,结构体中可以包含其它数据。所以,如同类一样,可以在结构体中定义任何想要展现的数据,以此来安排结构体在内存中的存放空间。以下是一些正确的例子。
type my_struct_name struct {
i int
j int
s string
}
type Rectangle struct {
length, width int //you can define multiple items of the same type on the same line separated by commas
area float64
}
至此,我们可以利用上面定义的 Rectangle
,访问其属性。
package main
import "fmt"
type Rectangle struct {
length, width int
}
func main() {
r := Rectangle{}
fmt.Println("Default rectangle is: ", r) //print default zero-ed value
}
Default rectangle is: {0 0}
通过上面的输出可以看出:结构体中的变量如果没有初始化,是自动赋值为 zero-value
,即 int
类型赋值为 0
,string
类型赋值为 ""
。所以对于结构体而言,其 zero-value
是由其内部属性决定的。
在下面的例子中,展示通过不同的方式初始化结构体的内部属性,并且将其打印到标准输出。
package main
import "fmt"
type Rectangle struct {
length, width int
name string
}
func main() {
r1 := Rectangle{2, 1, "my_r1"} //initialize values in order they are defined in struct
fmt.Println("Rectangle r1 is: ", r1)
r2 := Rectangle{width:3, name:"my_r2", length:4} //initialize values by variable name in any order
fmt.Println("Rectangle r2 is: ", r2)
pr := new (Rectangle) //get pointer to an instance with new keyword
(*pr).width = 6 //set value using . notation by dereferencing pointer.
pr.length = 8 //set value using . notation - same as previous. There is no -> operator like in c++. Go automatically converts
pr.name = "ptr_to_rectangle"
fmt.Println("Rectangle pr as address is: ", pr) //Go performs default printing of structs
fmt.Println("Rectangle pr as value is: ", *pr) //address and value are differentiated with an & symbol
}
Rectangle r1 is: {2 1 my_r1}
Rectangle r2 is: {4 3 my_r2}
Rectangle pr as address is: &{8 6 ptr_to_rectangle}
Rectangle pr as value is: {8 6 ptr_to_rectangle}
通过以上的例子,需要注意以下几点:
{}
可以初始化属性值,注意赋值时是按照声明的顺序通过 ,
分割。r1 := Rectangle{2, 1, "my_r1"}
变量名:值
的形式赋值。r2 := Rectangle{width:3, name:"my_r2", length:4}
new
可以获得一个对象的指针。*
操作符是可以不需要。Go
根据其结构体的属性,提供默认的打印机制。其它语言有 public
、protected
、private
等声明属性和方法对于不同上下文的可见性。在遇见 Go
之前,我觉得这样的设计无可厚非。Go
对于可见性的支持如此简单,一开始你可能认为这个设计太拙劣了。废话少说,在 Go
中,如果变了的首字母大写,即表明对于外包是可见的。嗯,就这么简单。
type notExported struct { //this struct is visible only in this package as it starts with small letter
}
type Exported struct { //variable starts with capital letter, so visible outside this package
notExportedVariable int //variable starts with small letter, so NOT visible outside package
ExportedVariable int //variable starts with capital letter, so visible outside package
s string //not exported
S string //exported
}
你可能会说,这是啥?是啥?而我要说,这简直是天才的设计啊。如此简单,如此明朗,不在需要任何额外的关键字。同时,通过查看某个变量的首字母就可以瞬间知道它的可见性,而无需在去费时去查找。其它语言,可能有一些对变量的规定来实现这种功能。但是 Go
将其发扬光大。
Golang一种神奇的语言,让我们一起进步