打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
指针,结构体,方法,接口

指针

Go 支持指针,允许在程序中通过引用传递值或者数据结构。

代码实例

package mainimport "fmt"// 我们将通过两个函数:`zeroval` 和 `zeroptr` 来比较指针和// 值类型的不同。`zeroval` 有一个 `int` 型参数,所以使用值// 传递。`zeroval` 将从调用它的那个函数中得到一个 `ival`// 形参的拷贝。func zeroval(ival int) {    ival = 0}// `zeroptr` 有一和上面不同的 `*int` 参数,意味着它用了一// 个 `int`指针。函数体内的 `*iptr` 接着_解引用_ 这个指针,// 从它内存地址得到这个地址对应的当前值。对一个解引用的指// 针赋值将会改变这个指针引用的真实地址的值。func zeroptr(iptr *int) {    *iptr = 0}func main() {    i := 1    fmt.Println("initial:", i)    zeroval(i)    fmt.Println("zeroval:", i)    // 通过 `&i` 语法来取得 `i` 的内存地址,例如一个变量    // `i` 的指针。    zeroptr(&i)    fmt.Println("zeroptr:", i)    // 指针也是可以被打印的。    fmt.Println("pointer:", &i)}

运行程序

# `zeroval` 在 `main` 函数中不能改变 `i` 的值,但是# `zeroptr` 可以,因为它有一个这个变量的内存地址的# 引用。$ go run pointers.goinitial: 1zeroval: 1zeroptr: 0pointer: 0x42131100

结构体

Go 的结构体 是各个字段字段的类型的集合。这在组织数据时非常有用。

代码实例

// Go 的_结构体_ 是各个字段字段的类型的集合。// 这在组织数据时非常有用。package mainimport "fmt"// 这里的 `person` 结构体包含了 `name` 和 `age` 两个字段。type person struct {    name string    age  int}func main() {    // 使用这个语法创建了一个新的结构体元素。    fmt.Println(person{"Bob", 20})    // 你可以在初始化一个结构体元素时指定字段名字。    fmt.Println(person{name: "Alice", age: 30})    // 省略的字段将被初始化为零值。    fmt.Println(person{name: "Fred"})    // `&` 前缀生成一个结构体指针。    fmt.Println(&person{name: "Ann", age: 40})    // 使用点来访问结构体字段。    s := person{name: "Sean", age: 50}    fmt.Println(s.name)    // 也可以对结构体指针使用`.` - 指针会被自动解引用。    sp := &s    fmt.Println(sp.age)    // 结构体是可变的。    sp.age = 51    fmt.Println(sp.age)}

运行程序

$ go run structs.go{Bob 20}{Alice 30}{Fred 0}&{Ann 40}Sean5051

方法

Go 支持在结构体类型中定义方法 。

代码实例

// Go 支持在结构体类型中定义_方法_ 。package mainimport "fmt"type rect struct {    width, height int}// 这里的 `area` 方法有一个_接收器类型_ `rect`。func (r *rect) area() int {    return r.width * r.height}// 可以为值类型或者指针类型的接收器定义方法。这里是一个// 值类型接收器的例子。func (r rect) perim() int {    return 2*r.width + 2*r.height}func main() {    r := rect{width: 10, height: 5}    // 这里我们调用上面为结构体定义的两个方法。    fmt.Println("area: ", r.area())    fmt.Println("perim:", r.perim())    // Go 自动处理方法调用时的值和指针之间的转化。你可以使    // 用指针来调用方法来避免在方法调用时产生一个拷贝,或者    // 让方法能够改变接受的数据。    rp := &r    fmt.Println("area: ", rp.area())    fmt.Println("perim:", rp.perim())}

运行程序

$ go run methods.go area:  50perim: 30area:  50perim: 30# 接下来我们将 Go 语言中组织和命名相关的方法集合的机# 制:接口。

接口

接口 是方法特征的命名集合。

代码实例

// _接口_ 是方法特征的命名集合。package mainimport "fmt"import "math"// 这里是一个几何体的基本接口。type geometry interface {    area() float64    perim() float64}// 在我们的例子中,我们将让 `square` 和 `circle` 实现// 这个接口type square struct {    width, height float64}type circle struct {    radius float64}// 要在 Go 中实现一个接口,我们只需要实现接口中的所有// 方法。这里我们让 `square` 实现了 `geometry` 接口。func (s square) area() float64 {    return s.width * s.height}func (s square) perim() float64 {    return 2*s.width + 2*s.height}// `circle` 的实现。func (c circle) area() float64 {    return math.Pi * c.radius * c.radius}func (c circle) perim() float64 {    return 2 * math.Pi * c.radius}// 如果一个变量的是接口类型,那么我们可以调用这个被命名的// 接口中的方法。这里有一个一通用的 `measure` 函数,利用这个// 特性,它可以用在任何 `geometry` 上。func measure(g geometry) {    fmt.Println(g)    fmt.Println(g.area())    fmt.Println(g.perim())}func main() {    s := square{width: 3, height: 4}    c := circle{radius: 5}    // 结构体类型 `circle` 和 `square` 都实现了 `geometry`    // 接口,所以我们可以使用它们的实例作为 `measure` 的参数。    measure(s)    measure(c)}

运行程序

$ go run interfaces.go{3 4}1214{5}78.5398163397448331.41592653589793# 要学习更多关于 Go 的接口的知识,看看这篇# [很棒的博文](http://jordanorelli.tumblr.com/post/32665860244/how-to-use-interfaces-in-go)。
动手实践是学习 IT 技术最有效的方式! 开始实验
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
golang: 详解interface和nil
Golang反射模型
Go秘密 - Interface{}: 空不是空
Golang面试必问——内存逃逸分析
Go 语言系列13:指针
详解 Go 的切片
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服