1、声明
type human struct {
name string
age int
height int
}
var h human
fmt.Printf("%p,%v\n",&h,h)
0xc000004460,{ 0 0}
简化写法
type human struct {
name string
age,heignt int
}
使用new
type human struct {
name string
age,heignt int
}
h :=new(human)
fmt.Printf("%p,%v\n",h,h)
0xc00005c420,&{ 0 0}
2、实例化
type human struct {
name string
age int
height int
}
var h1 human
h1.name="张三"
h1.age=20
h1.height=180
h2:=human{"李四",21,175}
var h3=human{"王五",20,181}
h4:=human{
name:"赵六",
age:22,
height:175,
}
h5:=human{
name:"赵六",
height:175,
}
fmt.Println(h1,h2,h3,h4,h5)
{张三 20 180} {李四 21 175} {王五 20 181} {赵六 22 175} {赵六 0 175}
3、结构体方法
GO的方法是下定义在一个接收者上的一个函数,接收者是某种类型的变量;GO的方法其实就是一个变种的函数
func (接收者) 函数名... 正常的函数结构
值传递
package main
import (
"fmt"
)
type human struct {
name string
age int
height int
}
func (h human) change(name string){
h.name=name
fmt.Println(h)
}
func main() {
h1:=human{
name:"张三",
age:22,
height:175,
}
fmt.Println(h1)
h1.change("李四")
fmt.Println(h1)
}
{张三 22 175}
{李四 22 175}
{张三 22 175}
引用传递
package main
import (
"fmt"
)
type human struct {
name string
age int
height int
}
func (h *human) change(name string){
h.name=name
fmt.Println(*h)
}
func main() {
h1:=human{
name:"张三",
age:22,
height:175,
}
fmt.Println(h1)
h1.change("李四")
fmt.Println(h1)
}
{张三 22 175}
{李四 22 175}
{李四 22 175}
4、匿名成员
字段的继承,如下,student可以直接方案human的字段name、age、height
type human struct {
name string
age int
height int
}
type student struct {
human
grade string
}
func main() {
stu1:=student{
human{"小明",8,140},"三年级",
}
fmt.Println(stu1)
fmt.Println(stu1.name,stu1.age,stu1.height,stu1.grade)
}
{{小明 8 140} 三年级}
小明 8 140 三年级
所有的内置类型和自定义类型都是可以作为匿名字段
type human struct {
name string
age int
height int
}
type student struct {
human
grade string
string
}
func main() {
stu1 := student{
human{"小明", 8, 140}, "三年级", "中关村一小",
}
fmt.Println(stu1)
fmt.Println(stu1.name, stu1.age, stu1.height, stu1.grade, stu1.string)
}
{{小明 8 140} 三年级 中关村一小}
张三 8 140 三年级 中关村一小
字段重载
type student struct {
human
grade string
string
name string
}
func main() {
stu1 := student{
human{"小明", 8, 140}, "三年级", "中关村一小", "张三",
}
fmt.Println(stu1.name,stu1.human.name)
}
张三 小明
匿名字段的方法
type human struct {
name string
age int
height int
}
type student struct {
human
grade string
string
name string
}
func (h *human)change(name string) {
h.name=name
fmt.Println(*h)
}
func main() {
stu1 := student{
human{"小明", 8, 140}, "三年级", "中关村一小", "张三",
}
stu1.change("大明白")
fmt.Println(stu1.name,stu1.human.name)
}
{大明白 8 140}
张三 大明白
5、匿名结构体
h1:= struct {
name string
age int
height int
}{
name:"张三",
age:22,
height:175,
}
fmt.Println(h1)
{张三 22 175}
结构体内嵌匿名结构体
type User struct {
RealName string
Age int
Cart struct {
Brand string
Price float64
}
}
func main() {
var u User
u.Age=19
u.RealName="小明"
u.Cart.Brand="奔驰"
u.Cart.Price=100
fmt.Println(u)
}
{小明 19 {奔驰 100}}
结构体内嵌匿名结构体数组
数组不是要有数量吗?
type User struct {
RealName string
Age int
Carts []struct {
Brand string
Price float64
}
}
func main() {
var u User
u.Age=19
u.RealName="小明"
u.Carts = []struct {
Brand string
Price float64
}{
{Brand:"本田",Price:100000.00},
{Brand:"宝马",Price:300000.00},
}
fmt.Println(u)
}
{小明 19 [{本田 100000} {宝马 300000}]}
type User struct {
RealName string
Age int
Carts []struct {
Brand string
Price float64
}
}
func main() {
user := User{}
user.RealName = "张三"
user.Age =40
brands:=[]string{"奔驰","宝马","丰田","大众"}
for _, cart := range brands {
item := struct {
Brand string
Price float64
}{Brand:cart,Price:100}
user.Carts = append(user.Carts, item)
}
fmt.Println(user)
}
{张三 40 [{奔驰 100} {宝马 100} {丰田 100} {大众 100}]}
可见性
6、tag
在golang中,命名都是推荐都是用驼峰方式,并且在首字母大小写有特殊的语法含义:包外无法引用。但是由经常需要和其它的系统进行数据交互,例如转成json格式,存储到mongodb啊等等。这个时候如果用属性名来作为键值可能不一定会符合项目要求。
Tag是结构体的元信息,可以在运行的时候通过反射的机制读取出来。 Tag在结构体字段的后方定义,由一对反引号包裹起来,具体的格式如下:
key1:"value1" key2:"value2"
下面的例子中Name和Age按照tag中json的格式输出了,Height原样输出。
package main
import (
"encoding/json"
"fmt"
)
type human struct {
Name string `json:"name"`
Age int `json:"age"`
Height int
}
func main() {
var user1 human
user1.Name = "测试名"
user1.Age=20
user1.Height = 180
u,err:=json.Marshal(user1)
if err == nil{
fmt.Printf("value: %s", u)
}
}
{"name":"测试名","age":20,"Height":180}
获取tag
h:=&human{"测试名",20,180}
rf:=reflect.TypeOf(h)
tag := rf.Elem().Field(0).Tag
fmt.Println(tag)
field0 := rf.Elem().Field(0)
fmt.Println(field0.Tag.Get("json"))
json:"name"
name
7、复制
struct是值类型,默认的复制就是深拷贝
h1:=human{"测试名",20,180}
h2:=h1
fmt.Printf("%p,%v\n",&h1,h1)
fmt.Printf("%p,%v\n",&h2,h2)
0xc000004460,{测试名 20 180}
0xc000004480,{测试名 20 180}
直接赋值指针地址
h1:=human{"测试名",20,180}
h3:=&h1
fmt.Printf("%p,%v\n",&h1,h1)
fmt.Printf("%p,%v\n",h3,*h3)
0xc000004460,{测试名 20 180}
0xc000004460,{测试名 20 180}
8、函数传参
值传递
type human struct {
Name string `json:"name"`
Age int `json:"age"`
Height int
}
func change(h human) {
h.Name="姓名"
fmt.Printf("%p,%v\n",&h,h)
}
func main() {
h1:=human{"测试名",20,180}
fmt.Printf("%p,%v\n",&h1,h1)
change(h1)
fmt.Printf("%p,%v\n",&h1,h1)
}
0xc00005c420,{测试名 20 180}
0xc00005c480,{姓名 20 180}
0xc00005c420,{测试名 20 180}
引用传递
func change(h *human) {
h.Name="姓名"
fmt.Printf("%p,%v\n",h,*h)
}
func main() {
h1:=human{"测试名",20,180}
fmt.Printf("%p,%v\n",&h1,h1)
change(&h1)
fmt.Printf("%p,%v\n",&h1,h1)
}
有疑问加站长微信联系(非本文作者)