Chinaunix首页 | 论坛 | 博客
  • 博客访问: 303704
  • 博文数量: 35
  • 博客积分: 825
  • 博客等级:
  • 技术积分: 913
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-11 09:44
文章分类

全部博文(35)

文章存档

2013年(10)

2012年(24)

2010年(1)

我的朋友

分类: Web开发

2013-02-03 00:17:11

Go allows you to define a struct that has fields but with no variable names. These fields are called anonymous fields. Let’s do a few examples to find out what they are and how they will be useful.

你可以定义一个结构体 这个结构体的字段可以没有变量的名字 只有类型 这些字段被称作是匿名字段 


In the below example, we have defined a Kitchen struct, which only contains the number of plates as a field. We define another field called House, which contains an instance of Kitchen as a field - but it is an anonymous field, because we have not given a variable name for it.

下面这个例子中 我们定义了Ktchen结构体 它只包含一个字段 就是numOfPlates 我们定义另一个结构体House House包含Kitchen实例 但是它是一个匿名的字段 因为这个字段没有对应的变量的名字 只有类型


Full code
package main import "fmt" 
type Kitchen struct { 
    numOfPlates int 
} 
 
type House struct { 
    Kitchen //anonymous field 
    numOfRooms int 
}
 
 func main() { 
    h := House{Kitchen{10}, 3} //to initialize you have to use composed type name. 
    fmt.Println("House h has this many rooms:", h.numOfRooms) //numOfRooms is a field of House 
    fmt.Println("House h has this many plates:", h.numOfPlates) //numOfPlates is a field of anonymous field Kitchen, so it can be referred to like a field of House 
    fmt.Println("The Kitchen contents of this house are:", h.Kitchen) //we can refer to the embedded struct in its entirety by referring to the name of the struct type 
}

House h has this many rooms: 3
House h has this many plates: 10
The Kitchen contents of this house are: {10}

The first important thing to note is that since we have defined Kitchen to be an anonymous field, it allows us to access its members as if they were members of the encompassing class. In comparison, if you were using a language like Java, you would have to do:

有几个值得注意的地方 首先 由于我们定义一个匿名的字段Kitchen go允许我们直接访问Kitchen结构体中的字段 numOfPlates就如同House中的字段一样 如果你有java经验 那么可以参考以下这段代码 :


Partial Java code
public class Kitchen { 
    public int numOfPlates; 
} 
 
public class House { 
    public Kitchen kitchen; 
} //and in main 
 
public static void main(String[] args) { 
    House h = new House(); 
    h.kitchen.numOfPlates = 10; //referred as a sub field item. 
}

The second important thing to note is that the composed field is still available to be accessed, but by its type name. So in this case the anonymous field for Kitchen has to be accessed ash.Kitchen. If you want to print the number of plates in the kitchen, then do this:fmt.Println(h.Kitchen.numOfPlates).

其次 我们可以通过被包含的结构体的类型名字 来访问这个被包含的结构体中的字段 h.Kitchen.numOfPlates


And the third important thing to note is how we had to use the type name when initializing the values as we did: h := House{Kitchen{10}, 3}. It is necessary here that you state the type name and provide its values within the corresponding curly braces. So h := House{{10}, 3}and h := House{10, 3} will cause compilation errors.

最后 当我们初始化House的时候 我们必须使用Kitchen类型名来初始化相应的匿名字段 所以像 h := House{{10}, 3} 或者 h := House{10, 3}方式来初始化House会导致编译错误


Anonymous fields - when naming conflicts arise

What happens when more than one of the composed structs or the composing struct has the same field name. If there is a field in an outer struct with the same name as a field in an inner anonymous struct, then the outer one is accessible by default. In the below example, both theKitchen and the House has a numOfLamps field, but since House is the outer struct, its numOfLamps hides Kitchen’s. If you still require to access the Kitchen’s numOfLamps, that is possible by referring to it via the type name: h.Kitchen.numOfLamps.

结构体可以包含多个字段 每个地段可能都是一个结构体 那么问题就就来了 这样会导致外层的定义会覆盖掉内层的定义 哎 一如既往的费脑啊 翻译不得体 那个例子来说事儿吧 下面这个例子中 Kitchen House都有numOfLamps字段 但是由于House是外层的结构提 它遮盖住了内层Kitchen的对应同名的字段 如果想要访问Kitchen中的字段 那么就需要使用 h.Kitchen.numOfLamps了


Full code
package main 
import "fmt" 
 
type Kitchen struct { 
    numOfLamps int 
} 
 
type House struct { 
    Kitchen 
    numOfLamps int 
} 
func main() { 
    h := House{Kitchen{2}, 10} //kitchen has 2 lamps, and the House has a total of 10 lamps 
    fmt.Println("House h has this many lamps:", h.numOfLamps) //this is ok - the outer House's numOfLamps hides the other one.  Output is 10. 
    fmt.Println("The Kitchen in house h has this many lamps:", h.Kitchen.numOfLamps) //we can still reach the number of lamps in the kitchen by using the type name h.Kitchen 
}

House h has this many lamps: 10
The Kitchen in house h has this many lamps: 2

So there is a rule on field resolution when the same field occurs at different levels of composition. But there is no rule when the fields are at the same level of composition - which means that when it occurs you need to resolve it yourself.

go提供这个字段解析的方式 但是只对不同层次的组合出现重名的情况有作用 如果重名出现在同一层次里 那么这个就需要你亲自出马解决啦


In the code below, both the Kitchen and the Bedroom have a field numOfLamps, and both are available as an anonymous field within House. Now if we referred to House.numOfLamps, the Go compiler cannot resolve whether you are referring to the numOfLamps within Kitchen or that within Bedroom and it throws an error.

下面这个例子中House有两个匿名字段 而且在这两个匿名字段类型中包含相同的字段名 numOfLamps 如果还是像上面那个例子中那样通过h.numOfLamps来访问 那么go就傻了 你需要明确地告诉go 你要哪个女人


Full file: structs2.go
package main 
import "fmt" 
 
type Kitchen struct { 
    numOfLamps int 
} 
 
type Bedroom struct { 
    numOfLamps int 
} 
 
type House struct { 
    Kitchen 
    Bedroom 
} 
 
func main() { 
    h := House{Kitchen{2}, Bedroom{3}} //kitchen has 2 lamps, Bedroom has 3 lamps 
    fmt.Println("Ambiguous number of lamps:", h.numOfLamps) //this is an error due to ambiguousness - is it Kitchen.numOfLamps or Bedroom.numOfLamps 
}

Compiler error
8g -o _go_.8 structs2.go
structs2.go:20: ambiguous DOT reference House.numOfLamps
make: *** [_go_.8] Error 1

To resolve this, you will have to refer to the required fields explicitly via the type name of the anonymous field. In the corrected example below, we’ve summed up the number of lamps in the kitchen and the bedroom by referring to the number of lamps in it via its type name.

可以通过h.Kitchen.numOfLamps, h.Bedrom.numOfLamps来访问相应的numOfLamps


package main 
import "fmt"
 
type Kitchen struct { 
    numOfLamps int 
} 
 
type Bedroom struct { 
    numOfLamps int 
} 
 
type House struct { 
    Kitchen 
    Bedroom 
} 
 
func main() { 
    h := House{Kitchen{2}, Bedroom{3}} 
    fmt.Println("House h has this many lamps:", h.Kitchen.numOfLamps + h.Bedroom.numOfLamps) //refer to fields via type name 
}

House h has this many lamps: 5
阅读(1809) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~