Add en/0.2.5.md syntax highlighting

This commit is contained in:
vCaesar
2017-04-09 14:52:41 +08:00
parent 2a9a362c56
commit ac11c27371
2 changed files with 166 additions and 156 deletions

View File

@@ -307,25 +307,27 @@ Now you may ask how I can pass the real `x` to the function.
We need use pointers here. We know variables are stored in memory and they have some memory addresses. So, if we want to change the value of a variable, we must change its memory address. Therefore the function `add1` has to know the memory address of `x` in order to change its value. Here we pass `&x` to the function, and change the argument's type to the pointer type `*int`. Be aware that we pass a copy of the pointer, not copy of value.
```Go
package main
import "fmt"
package main
// simple function to add 1 to a
func add1(a *int) int {
*a = *a+1 // we changed value of a
return *a // return new value of a
}
import "fmt"
func main() {
x := 3
// simple function to add 1 to a
func add1(a *int) int {
*a = *a + 1 // we changed value of a
return *a // return new value of a
}
fmt.Println("x = ", x) // should print "x = 3"
func main() {
x := 3
x1 := add1(&x) // call add1(&x) pass memory address of x
fmt.Println("x = ", x) // should print "x = 3"
x1 := add1(&x) // call add1(&x) pass memory address of x
fmt.Println("x+1 = ", x1) // should print "x+1 = 4"
fmt.Println("x = ", x) // should print "x = 4"
}
fmt.Println("x+1 = ", x1) // should print "x+1 = 4"
fmt.Println("x = ", x) // should print "x = 4"
}
```
Now we can change the value of `x` in the functions. Why do we use pointers? What are the advantages?

View File

@@ -3,12 +3,12 @@
## struct
We can define new types of containers of other properties or fields in Go just like in other programming languages. For example, we can create a type called `person` to represent a person, with fields name and age. We call this kind of type a `struct`.
type person struct {
name string
age int
}
```Go
type person struct {
name string
age int
}
```
Look how easy it is to define a `struct`!
There are two fields.
@@ -17,75 +17,77 @@ There are two fields.
- `age` is a `int` used to store a person's age.
Let's see how to use it.
```Go
type person struct {
name string
age int
}
type person struct {
name string
age int
}
var P person // p is person type
P.name = "Astaxie" // assign "Astaxie" to the field 'name' of p
P.age = 25 // assign 25 to field 'age' of p
fmt.Printf("The person's name is %s\n", P.name) // access field 'name' of p
var P person // p is person type
P.name = "Astaxie" // assign "Astaxie" to the field 'name' of p
P.age = 25 // assign 25 to field 'age' of p
fmt.Printf("The person's name is %s\n", P.name) // access field 'name' of p
```
There are three more ways to define a struct.
- Assign initial values by order
P := person{"Tom", 25}
```Go
P := person{"Tom", 25}
```
- Use the format `field:value` to initialize the struct without order
P := person{age:24, name:"Bob"}
```Go
P := person{age:24, name:"Bob"}
```
- Define an anonymous struct, then initialize it
P := struct{name string; age int}{"Amy",18}
```Go
P := struct{name string; age int}{"Amy",18}
```
Let's see a complete example.
```Go
package main
package main
import "fmt"
import "fmt"
// define a new type
type person struct {
name string
age int
// define a new type
type person struct {
name string
age int
}
// compare the age of two people, then return the older person and differences of age
// struct is passed by value
func Older(p1, p2 person) (person, int) {
if p1.age > p2.age {
return p1, p1.age - p2.age
}
return p2, p2.age - p1.age
}
// compare the age of two people, then return the older person and differences of age
// struct is passed by value
func Older(p1, p2 person) (person, int) {
if p1.age>p2.age {
return p1, p1.age-p2.age
}
return p2, p2.age-p1.age
}
func main() {
var tom person
func main() {
var tom person
// initialization
tom.name, tom.age = "Tom", 18
// initialization
tom.name, tom.age = "Tom", 18
// initialize two values by format "field:value"
bob := person{age: 25, name: "Bob"}
// initialize two values by format "field:value"
bob := person{age:25, name:"Bob"}
// initialize two values with order
paul := person{"Paul", 43}
// initialize two values with order
paul := person{"Paul", 43}
tb_Older, tb_diff := Older(tom, bob)
tp_Older, tp_diff := Older(tom, paul)
bp_Older, bp_diff := Older(bob, paul)
tb_Older, tb_diff := Older(tom, bob)
tp_Older, tp_diff := Older(tom, paul)
bp_Older, bp_diff := Older(bob, paul)
fmt.Printf("Of %s and %s, %s is older by %d years\n", tom.name, bob.name, tb_Older.name, tb_diff)
fmt.Printf("Of %s and %s, %s is older by %d years\n", tom.name, bob.name, tb_Older.name, tb_diff)
fmt.Printf("Of %s and %s, %s is older by %d years\n", tom.name, paul.name, tp_Older.name, tp_diff)
fmt.Printf("Of %s and %s, %s is older by %d years\n", tom.name, paul.name, tp_Older.name, tp_diff)
fmt.Printf("Of %s and %s, %s is older by %d years\n", bob.name, paul.name, bp_Older.name, bp_diff)
}
fmt.Printf("Of %s and %s, %s is older by %d years\n", bob.name, paul.name, bp_Older.name, bp_diff)
}
```
### embedded fields in struct
I've just introduced to you how to define a struct with field names and type. In fact, Go supports fields without names, but with types. We call these embedded fields.
@@ -93,120 +95,126 @@ I've just introduced to you how to define a struct with field names and type. In
When the embedded field is a struct, all the fields in that struct will implicitly be the fields in the struct in which it has been embdedded.
Let's see one example.
```Go
package main
package main
import "fmt"
import "fmt"
type Human struct {
name string
age int
weight int
}
type Human struct {
name string
age int
weight int
}
type Student struct {
Human // embedded field, it means Student struct includes all fields that Human has.
specialty string
}
type Student struct {
Human // embedded field, it means Student struct includes all fields that Human has.
specialty string
}
func main() {
// initialize a student
mark := Student{Human{"Mark", 25, 120}, "Computer Science"}
func main() {
// initialize a student
mark := Student{Human{"Mark", 25, 120}, "Computer Science"}
// access fields
fmt.Println("His name is ", mark.name)
fmt.Println("His age is ", mark.age)
fmt.Println("His weight is ", mark.weight)
fmt.Println("His specialty is ", mark.specialty)
// modify notes
mark.specialty = "AI"
fmt.Println("Mark changed his specialty")
fmt.Println("His specialty is ", mark.specialty)
// modify age
fmt.Println("Mark become old")
mark.age = 46
fmt.Println("His age is", mark.age)
// modify weight
fmt.Println("Mark is not an athlet anymore")
mark.weight += 60
fmt.Println("His weight is", mark.weight)
}
// access fields
fmt.Println("His name is ", mark.name)
fmt.Println("His age is ", mark.age)
fmt.Println("His weight is ", mark.weight)
fmt.Println("His specialty is ", mark.specialty)
// modify notes
mark.specialty = "AI"
fmt.Println("Mark changed his specialty")
fmt.Println("His specialty is ", mark.specialty)
// modify age
fmt.Println("Mark become old")
mark.age = 46
fmt.Println("His age is", mark.age)
// modify weight
fmt.Println("Mark is not an athlet anymore")
mark.weight += 60
fmt.Println("His weight is", mark.weight)
}
```
![](images/2.4.student_struct.png?raw=true)
Figure 2.7 Embedding in Student and Human
We see that we can access the `age` and `name` fields in Student just like we can in Human. This is how embedded fields work. It's very cool, isn't it? Hold on, there's something cooler! You can even use Student to access Human in this embedded field!
```Go
mark.Human = Human{"Marcus", 55, 220}
mark.Human.age -= 1
```
All the types in Go can be used as embedded fields.
```Go
package main
package main
import "fmt"
import "fmt"
type Skills []string
type Skills []string
type Human struct {
name string
age int
weight int
}
type Human struct {
name string
age int
weight int
}
type Student struct {
Human // struct as embedded field
Skills // string slice as embedded field
int // built-in type as embedded field
specialty string
}
type Student struct {
Human // struct as embedded field
Skills // string slice as embedded field
int // built-in type as embedded field
specialty string
}
func main() {
// initialize Student Jane
jane := Student{Human:Human{"Jane", 35, 100}, specialty:"Biology"}
// access fields
fmt.Println("Her name is ", jane.name)
fmt.Println("Her age is ", jane.age)
fmt.Println("Her weight is ", jane.weight)
fmt.Println("Her specialty is ", jane.specialty)
// modify value of skill field
jane.Skills = []string{"anatomy"}
fmt.Println("Her skills are ", jane.Skills)
fmt.Println("She acquired two new ones ")
jane.Skills = append(jane.Skills, "physics", "golang")
fmt.Println("Her skills now are ", jane.Skills)
// modify embedded field
jane.int = 3
fmt.Println("Her preferred number is ", jane.int)
}
func main() {
// initialize Student Jane
jane := Student{Human: Human{"Jane", 35, 100}, specialty: "Biology"}
// access fields
fmt.Println("Her name is ", jane.name)
fmt.Println("Her age is ", jane.age)
fmt.Println("Her weight is ", jane.weight)
fmt.Println("Her specialty is ", jane.specialty)
// modify value of skill field
jane.Skills = []string{"anatomy"}
fmt.Println("Her skills are ", jane.Skills)
fmt.Println("She acquired two new ones ")
jane.Skills = append(jane.Skills, "physics", "golang")
fmt.Println("Her skills now are ", jane.Skills)
// modify embedded field
jane.int = 3
fmt.Println("Her preferred number is ", jane.int)
}
```
In the above example, we can see that all types can be embedded fields and we can use functions to operate on them.
There is one more problem however. If Human has a field called `phone` and Student has a field with same name, what should we do?
Go use a very simple way to solve it. The outer fields get upper access levels, which means when you access `student.phone`, we will get the field called phone in student, not the one in the Human struct. This feature can be simply seen as field `overload`ing.
```Go
package main
package main
import "fmt"
import "fmt"
type Human struct {
name string
age int
phone string // Human has phone field
}
type Human struct {
name string
age int
phone string // Human has phone field
}
type Employee struct {
Human // embedded field Human
specialty string
phone string // phone in employee
}
type Employee struct {
Human // embedded field Human
specialty string
phone string // phone in employee
}
func main() {
Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
fmt.Println("Bob's work phone is:", Bob.phone)
// access phone field in Human
fmt.Println("Bob's personal phone is:", Bob.Human.phone)
}
func main() {
Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
fmt.Println("Bob's work phone is:", Bob.phone)
// access phone field in Human
fmt.Println("Bob's personal phone is:", Bob.Human.phone)
}
```
## Links
- [Directory](preface.md)