假设你需要解析一堆数据,在解析的过程中发现某个字段的值不同,即为一种类型,每种类型对应的是一个完全不同的结构。比如1对应的结构为user,2对应的为desk,数据中有很多这样的类型,我们解析不同的结构后希望能存储结构体,然后在使用时,可以将这些结构体展开,并根据不同类型做出不同的处理。
我们假设有两种类型,一种为User, 一种为Desk
type User struct {
name string
age int
}
type Desk struct {
price float64
size int
}
当我们在解析数据的时候,不管是User类型,还是Desk类型,我们希望能将之放在一个数据结构中,便于程序处理,此时可设置一个结构,将两种类型以interface的方式存放起来,结果如下:
type Node struct {
msgType int
i interface{}
}
当我们发现msgType为1时,i存放的是User类型指针,当msgType为2时,存放的则为Desk指针
最后我们返回Node指针:
func Parse(msgType int) (*Node, error) {
a := rand.Intn(50)
s := strconv.Itoa(a)
node := new(Node)
if msgType == 1 {
u := new(User)
u.name = "Name" + s
u.age = a
node.msgType = msgType
node.i = u
return node, nil
} else if msgType == 2 {
d := new(Desk)
d.price = float64(a) * 0.8
d.size = a
node.msgType = msgType
node.i = d
return node, nil
}
return nil, errors.New("Error!!!")
}
现在我们开始不断解析数据,一连解析4个数据后得到两个User类型的数据和两个Desk类型的数据,这4个数据都存于Node中,然后放入nodes数组中
var nodes []*Node
for i := 1; i <= 4; i++ {
node, _ := Parse(i%2 + 1)
if node != nil {
nodes = append(nodes, node)
}
}
数据解析完成后,我们封装了针对这个解析结果的处理。处理时我们根据msgType进行断言,如果msgType为1,则认为数据类型为User,如果msgType为2,认为数据类型为Desk。并根据不同的类型进行不同的处理
func Deal(nodes []*Node) {
for _, v:= range nodes {
if v.msgType == 1 {
fmt.Printf("Name: %s, age: %d\n", v.i.(*User).name, v.i.(*User).age)
} else if v.msgType == 2 {
fmt.Printf("size: %d, price: %f\n", v.i.(*Desk).size, v.i.(*Desk).price)
}
}
}
最后附上全部测试代码:
package tests
import (
"errors"
"fmt"
"math/rand"
"strconv"
"testing"
)
type User struct {
name string
age int
}
type Desk struct {
price float64
size int
}
type Node struct {
msgType int
i interface{}
}
func Parse(msgType int) (*Node, error) {
a := rand.Intn(50)
s := strconv.Itoa(a)
node := new(Node)
if msgType == 1 {
u := new(User)
u.name = "Name" + s
u.age = a
node.msgType = msgType
node.i = u
return node, nil
} else if msgType == 2 {
d := new(Desk)
d.price = float64(a) * 0.8
d.size = a
node.msgType = msgType
node.i = d
return node, nil
}
return nil, errors.New("Error!!!")
}
func Deal(nodes []*Node) {
for _, v:= range nodes {
if v.msgType == 1 {
fmt.Printf("Name: %s, age: %d\n", v.i.(*User).name, v.i.(*User).age)
} else if v.msgType == 2 {
fmt.Printf("size: %d, price: %f\n", v.i.(*Desk).size, v.i.(*Desk).price)
}
}
}
func TestInterface(t *testing.T) {
rand.Seed(10000)
var nodes []*Node
for i := 1; i <= 4; i++ {
node, _ := Parse(i%2 + 1)
if node != nil {
nodes = append(nodes, node)
}
}
Deal(nodes)
}
附上运行结果:
=== RUN TestInterface
size: 46, price: 36.800000
Name: Name31, age: 31
size: 45, price: 36.000000
Name: Name12, age: 12
--- PASS: TestInterface (0.00s)
PASS
下一节应该是网络数据派发的简单模型