Go 面向对象简明教程
如果把 C 变成 C++, 那么 C 就消失了。
引子
在云原生时代,Go 变成了一门受人关注的编程语言。个人觉得,对于 Java 业务开发人员来说,熟悉一门接近系统级别的编程语言,还是有必要的。多熟悉下系统级别的原理机制,而不是局限于应用层的框架和库的使用上,对程序员来说,也是一件有益的事情。何况,谁能说,云原生不会是下一波技术浪潮呢?
之前写过一篇, “Go语言初尝”,算是尝个鲜,现在公司开始转 Go,需要正儿八经深入学习一下。
定义类
Go 定义类的形式与 C 语言定义结构体很相似,连关键字 struct 都是一样的,不愧是对 C 情有独钟!
Go 定义类:
define.go
package define
type FlowResult struct {
Code int
}
C 定义结构体:
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
注意到 Code 是首字母大写。这涉及到 Go 可见性的一条规则:
- package A 里的首字母大写的成员变量或成员方法,对所有包可见,相当于 public 变量或方法;
- package A 里的首字母小写的成员变量或成员方法,对 package A 之外的其它包不可见。
比如,可以在 package main 里创建 FlowResult 的对象:
package main
import (
"fmt"
"github.com/qt/eventflow/pkg/define"
)
func testConstruct() {
result := &define.FlowResult{ 200 }
fmt.Println(result)
}
如果把 Code 改成 code,同样的代码会报错:
implicit assignment of unexported field 'code' in define.FlowResult literal
一般来说,写过 Java 的童鞋倾向于将字段对外不可见(private),如下:
package compos
type AgentDetection struct {
eventId string
agentId string
osType int
}
这时候,在 package compos 之外的其它包是无法如下面初始化的,报错同上。
package main
import (
"fmt"
"github.com/qt/eventflow/pkg/compos"
)
agent := &compos.AgentDetection{ "eventId", "agentId", 1 }
// error : implicit assignment of unexported field 'eventId' in compos.AgentDetection literal
那么,怎么创建 AgentDetection 对象呢?虽然在 package compos 外的其它包里无法如上创建,但在 package compos 里是可以这么创建的(这是 Go 提供的默认构造器)。 可以在 compos 里提供一个方法包装一下。注意到,返回值是 *AgentDetection,而赋值是 &AgentDetection。你能猜到为什么返回指针吗?
package compos
func (AgentDetection) Instanceof(agentId string, osType int) *AgentDetection {
eventId := strconv.Itoa(int((time.Now().Unix()))) + strconv.Itoa(getRandomInt())
return &AgentDetection{ eventId, agentId, osType}
}
在其它包里使用如下:
package main
detection := compos.AgentDetection{}.Instanceof("agentId", 1)
fmt.Println(detection)
注意,如果把 Instanceof 改成 instanceof ,就会报错:
compos.AgentDetection{}.instanceof undefined (cannot refer to unexported field or method instanceof)
默认构造器
Java 只提供了无参的默认构造器。Go 提供了丰富的默认构造器。从上面例子可以看到,即使并没有声明一个 AgentDetection(eventId, agentId, osType),也可以直接通过 &AgentDetection{eventId, agentId, osType} 来创建一个 AgentDetection 对象。
Go 还提供了自动的命名构造器,如下所示,仅对 agentId, osType 赋值。运行后可知,仅对 agentId, osType 赋值,而 eventId 是 空字符串。
func (AgentDetection) InstanceByNaming(agentId string, osType int) *AgentDetection {
return &AgentDetection{ agentId:agentId, osType: osType}
}
detection2 := compos.AgentDetection{}.InstanceByNaming("agentId", 1)
fmt.Println(detection2)
fmt.Println("eventId: " + detection2.GetEventId())
空对象
compos.AgentDetection{} 是什么含义?这会创建一个空的 AgentDetection 对象,然后用这个对象去创建一个有值的对象。
empty := compos.AgentDetection{}
fmt.Println(reflect.TypeOf(empty)) // print : compos.AgentDetection
啊,这样岂不是创建了两个对象?可以这样:
var emp compos.AgentDetection
demp := emp.Instanceof("agentId", 1)
fmt.Printf("demp: %v\n", demp)
fmt.Println(emp)
fmt.Println(reflect.TypeOf(emp))
咦?竟然没有出现类似 NPE 的异常?实际上,即使声明为 var emp compos.AgentDetection, emp 也并不是 nil, 而是一个空对象。猜猜下面分别打印什么 ?
func testEmptyObject() {
var emp compos.AgentDetection
p1 := &emp
demp := emp.Instanceof("agentId", 1)
fmt.Printf("demp: %v\n", demp)
fmt.Println(emp)
fmt.Println(reflect.TypeOf(emp))
var emp2 compos.AgentDetection
p2 := &emp2
fmt.Println("compare reference to empty agentDetection")
compareObj(emp, emp2)
fmt.Println("compare pointers to empty agentDetection")
compareAgentDetection(p1, p2)
emp3 := &compos.AgentDetection{}
emp4 := &compos.AgentDetection{}
fmt.Println("compare pointers to empty2 agentDetection")
compareAgentDetection(emp3, emp4)
}
func compareObj(o1 interface{}, o2 interface{}) {
fmt.Printf("o1: %v\n", o1)
fmt.Printf("o2: %v\n", o2)
fmt.Printf("o1-p: %p\n", o1)
fmt.Printf("o2-p: %p\n", o2)
fmt.Printf("&o1: %v\n", &o1)
fmt.Printf("&o2: %v\n", &o2)
fmt.Printf("o1 == o2: %v\n", (o1 == o2))
fmt.Printf("&o1 == &o2: %v\n", &o1 == &o2)
}
func compareAgentDetection(adp1 *compos.AgentDetection, adp2 *compos.AgentDetection) {
fmt.Printf("adp1: %v\n", adp1)
fmt.Printf("adp2: %v\n", adp2)
fmt.Printf("adp1-p: %p\n", adp1)
fmt.Printf("adp2-p: %p\n", adp2)
fmt.Printf("*adp1: %v\n", *adp1)
fmt.Printf("*adp2: %v\n", *adp2)
fmt.Printf("&adp1: %v\n", &adp1)
fmt.Printf("&adp2: %v\n", &adp2)
fmt.Printf("adp1 == adp2: %v\n", (adp1 == adp2))
fmt.Printf("&adp1 == &adp2: %v\n", &adp1 == &adp2)
fmt.Printf("*adp1 == *adp2: %v\n", *adp1 == *adp2)
}
好像陷入了一个鸡生蛋还是蛋生鸡的问题。要调用 Instanceof 方法去创建一个对象,首先得有这样一个对象?其实解决这个问题的办法有两种:
- 把 Instanceof 变成一个普通的函数,而不是 AgentDetection 的方法;
- 将 Instanceof 变成一个工厂类 AgentDetectionFactory 的方法。
采用第一种方式,定义一个 NewAgentDetection 可见的方法,
func NewAgentDetection(agentId string, osType int) *AgentDetection {
eventId := strconv.Itoa(int((time.Now().Unix()))) + strconv.Itoa(getRandomInt())
return &AgentDetection{ eventId, agentId, osType}
}
然后在 package main 里就可以这样初始化:
detection3 := compos.NewAgentDetection("agentId", 1)
fmt.Printf("d3: %v\n", detection3)
采用第二种方法,定义一个关联的工厂类 AgentDetectionFactory:
type AgentDetectionFactory struct {
}
func (*AgentDetectionFactory) Instanceof(agentId string, osType int) *AgentDetection {
eventId := strconv.Itoa(int((time.Now().Unix()))) + strconv.Itoa(getRandomInt())
return &AgentDetection{ eventId, agentId, osType}
}
func (*AgentDetectionFactory) InstanceByNaming(agentId string, osType int) *AgentDetection {
return &AgentDetection{ agentId:agentId, osType: osType}
}
func testFactoryMethod() {
adf := &compos.AgentDetectionFactory{}
detection := adf.Instanceof("agentId", 2)
fmt.Printf( "detection from factory method: %v\n", detection)
}
单例
像 AgentDetectionFactory 这样的类,在 Java 中是典型的单例。那么,在 Go 里怎么实现单例呢? 在网上摘抄的(DCL 思想):
var (
facLock *sync.Mutex = &sync.Mutex{}
adf *AgentDetectionFactory
)
func GetAgentFactoryInstance() *AgentDetectionFactory {
if adf == nil {
facLock.Lock()
defer facLock.Unlock()
if adf == nil {
adf = &AgentDetectionFactory{}
fmt.Println("Empty single instance...")
}
}
return adf
}
做个简单的测试。猜猜下面分别打印什么 ?
func testSingleton() {
adf := compos.GetAgentFactoryInstance()
adf2 := compos.GetAgentFactoryInstance()
compare(adf, adf2)
}
func compare(p1 *compos.AgentDetectionFactory, p2 *compos.AgentDetectionFactory) {
fmt.Printf("adf: %v\n", p1)
fmt.Printf("adf2: %v\n", p2)
fmt.Printf("adf-p: %p\n", p1)
fmt.Printf("adf2-p: %p\n", p2)
fmt.Printf("*adf: %v\n", *p1)
fmt.Printf("*adf2: %v\n", *p2)
fmt.Printf("&adf: %v\n", &p1)
fmt.Printf("&adf2: %v\n", &p2)
fmt.Printf("adf == adf2: %v\n", (p1 == p2))
fmt.Printf("&adf == &adf2: %v\n", &p1 == &p2)
fmt.Printf("*adf == *adf2: %v\n", *p1 == *p2)
}
类的方法
实际上,前面已经给出了类的方法定义,有两种形式,如下所示:
func (AgentDetection) InstanceByNaming(agentId string, osType int) *AgentDetection {
return &AgentDetection{ agentId:agentId, osType: osType}
}
func (*AgentDetectionFactory) Instanceof(agentId string, osType int) *AgentDetection {
eventId := strconv.Itoa(int((time.Now().Unix()))) + strconv.Itoa(getRandomInt())
return &AgentDetection{ eventId, agentId, osType}
}
一个是前面不带星号的,一个是前面带星号的。有什么区别呢 ? 如果不涉及接口,看上去都是没问题的:
func testClassMethod() {
withoutStar := compos.AgentDetection{}
ad := withoutStar.Instanceof("agentId111", 1)
fmt.Printf("ad: %v\n", ad)
withoutStar2 := &compos.AgentDetection{}
ad2 := withoutStar2.Instanceof("agentId222", 1)
fmt.Printf("ad: %v\n", ad2)
withStar := compos.AgentDetectionFactory{}
ad3 := withStar.Instanceof("agentId333", 1)
fmt.Printf("ad3: %v\n", ad3)
withStar2 := &compos.AgentDetectionFactory{}
ad4 := withStar2.Instanceof("agentId444", 1)
fmt.Printf("ad4: %v\n", ad4)
}
接口
终于谈到接口了。事情稍微变得有趣了些。 接口定义也比较简单:
type FlowComponent interface {
GetName() string
Process(context *Context) (result define.FlowResult, error error)
}
但类如何去实现接口呢? 这就涉及到关于接口的一个重要争论:
- 显式地说明实现关系,比如 Java 的 implements ;
- 实现指定的行为接口即可,比如 Go 。
即: 如果会游泳的动物具备 CanSwim { swim() }, 那么任何 实现了 swim() 方法的类都是 CanSwim 对象,而无需显式指定与 CanSwim 的关系。CanSwim 对于谁实现了它一无所知,但是 Java 的接口可以知道谁实现了它。比如:
func (hcc HostCompletionComponent) GetName() string {
return "compos.HostCompletionComponent"
}
func (hcc HostCompletionComponent) Process(context *Context) (result define.FlowResult, error error) {
event := context.GetEventData()
err := (*event).SetOsType(-1)
if err != nil {
return define.FlowResult{define.TERMINAL}, err
}
fmt.Println(*event)
return define.FlowResult{define.CONTINUE}, nil
}
type DetectionSaver struct {
}
func (saver DetectionSaver) Process(ctx *Context) (result define.FlowResult, error error) {
event := ctx.GetEventData()
fmt.Printf("save detection. eventId: %s", (*event).GetEventId())
return define.FlowResult{200}, nil
}
func (hcc DetectionSaver) GetName() string {
return "compos.DetectionSaver"
}
使用:
// 直接赋值
fc := &compos.HostCompletionComponent{}
saver := &compos.DetectionSaver{}
fc.Process(ctx)
saver.Process(ctx)
// 数组赋值
components := [...]compos.FlowComponent{&compos.HostCompletionComponent{}, &compos.DetectionSaver{} }
for _, comp := range components {
res, err := comp.Process(ctx)
if err != nil {
fmt.Println(err)
}
if res.Code == define.TERMINAL {
panic("Flow terminated")
}
}
HostCompletionComponent, DetectionSaver 都可以做成单例的。
完整程序
下面是一个较为完整的小程序,基本涵盖了 Go 的常用必知必会的语言特性。
目录结构
eventflow-go
cmd
main.go
pkg
define
define.go
compos
components.go
yaml
readyaml.go
configs
eventflow.yml
define.go
package define
const (
CONTINUE = 200
TERMINAL = -1
)
type IllegalArgumentError struct {
Msg string
Err error
}
func (e *IllegalArgumentError) Error() string {
return e.Msg
}
type FlowResult struct {
Code int
}
// Do not need declared explicitly
//func NewFlowResult(code int) FlowResult {
// return FlowResult{code}
//}
type EventData interface {
GetData() interface{}
GetType() string
GetEventId() string
SetOsType(i int) error
}
components.go
package compos
import (
"fmt"
"math/rand"
"reflect"
"strconv"
"sync"
"time"
"github.com/qt/eventflow/pkg/define"
)
type AgentDetection struct {
eventId string
agentId string
osType int
}
func getRandomInt() int {
nanotime := int64(time.Now().Nanosecond())
rand.Seed(nanotime)
return rand.Int()
}
func (AgentDetection) Instanceof(agentId string, osType int) *AgentDetection {
eventId := strconv.Itoa(int((time.Now().Unix()))) + strconv.Itoa(getRandomInt())
return &AgentDetection{ eventId, agentId, osType}
}
func (AgentDetection) InstanceByNaming(agentId string, osType int) *AgentDetection {
return &AgentDetection{ agentId:agentId, osType: osType}
}
func NewAgentDetection(agentId string, osType int) *AgentDetection {
eventId := strconv.Itoa(int((time.Now().Unix()))) + strconv.Itoa(getRandomInt())
return &AgentDetection{ eventId, agentId, osType}
}
func (detection *AgentDetection) GetData() interface{} {
return detection
}
func (detection *AgentDetection) GetType() string {
return "Detection"
}
func (detection *AgentDetection) GetEventId() string {
return detection.eventId
}
func (detection *AgentDetection) GetAgentId() string {
return detection.agentId
}
func (detection *AgentDetection) SetOsType(osType int) (err error) {
if osType != 1 && osType != 2 {
return &define.IllegalArgumentError{"invalid parameter", nil}
}
(*detection).osType = osType
return nil
}
type AgentDetectionFactory struct {
}
func (*AgentDetectionFactory) Instanceof(agentId string, osType int) *AgentDetection {
eventId := strconv.Itoa(int((time.Now().Unix()))) + strconv.Itoa(getRandomInt())
return &AgentDetection{ eventId, agentId, osType}
}
func (*AgentDetectionFactory) InstanceByNaming(agentId string, osType int) *AgentDetection {
return &AgentDetection{ agentId:agentId, osType: osType}
}
var (
facLock *sync.Mutex = &sync.Mutex{}
adf *AgentDetectionFactory
)
func GetAgentFactoryInstance() *AgentDetectionFactory {
if adf == nil {
facLock.Lock()
defer facLock.Unlock()
if adf == nil {
adf = &AgentDetectionFactory{}
fmt.Println("AgentDetectionFactory single instance...")
}
}
return adf
}
type Context struct {
event *define.EventData
}
func (ctx Context) New(e *define.EventData) *Context {
return &Context{ e }
}
// Do not need declared explicitly
//func NewContext(event *EventData) *Context {
// return &Context{event }
//}
func (ctx *Context) GetEventData() *define.EventData {
return ctx.event
}
const (
HostCompletionComponentName = iota
DetectionSaverName
)
type FlowComponent interface {
GetName() string
Process(context *Context) (result define.FlowResult, error error)
}
func getName(o interface{}) string {
return fmt.Sprintf("%v", reflect.TypeOf(o))
}
type HostCompletionComponent struct {
}
func (hcc HostCompletionComponent) GetName() string {
return getName(hcc)
}
func (hcc HostCompletionComponent) Process(context *Context) (result define.FlowResult, error error) {
event := context.GetEventData()
err := (*event).SetOsType(1)
if err != nil {
return define.FlowResult{define.TERMINAL}, err
}
fmt.Println(*event)
return define.FlowResult{define.CONTINUE}, nil
}
type DetectionSaver struct {
}
func (saver DetectionSaver) Process(ctx *Context) (result define.FlowResult, error error) {
event := ctx.GetEventData()
fmt.Printf("save detection. eventId: %s\n", (*event).GetEventId())
return define.FlowResult{200}, nil
}
func (saver DetectionSaver) GetName() string {
return getName(saver)
}
type Empty struct {
}
func (Empty) Process(ctx *Context) (result define.FlowResult, error error) {
return define.FlowResult{200}, nil
}
func (empty Empty) GetName() string {
return getName(empty)
}
var (
lock *sync.Mutex = &sync.Mutex{}
hostComponent *HostCompletionComponent
detectionSaverComponent *DetectionSaver
empty *Empty
componentFactory *ComponentFactory
)
func GetHostCompletionComponentInstance() *HostCompletionComponent {
if hostComponent == nil {
lock.Lock()
defer lock.Unlock()
if hostComponent == nil {
hostComponent = &HostCompletionComponent{}
fmt.Println("HostCompletionComponent single instance...")
}
}
return hostComponent
}
func GetDetectionSaverComponentInstance() *DetectionSaver {
if detectionSaverComponent == nil {
lock.Lock()
defer lock.Unlock()
if detectionSaverComponent == nil {
detectionSaverComponent = &DetectionSaver{}
fmt.Println("DetectionSaver single instance...")
}
}
return detectionSaverComponent
}
func GetEmptyInstance() *Empty {
if empty == nil {
lock.Lock()
defer lock.Unlock()
if empty == nil {
empty = &Empty{}
fmt.Println("Empty single instance...")
}
}
return empty
}
type ComponentFactory struct {
}
func GetComponentFactoryInstance() *ComponentFactory {
if componentFactory == nil {
lock.Lock()
defer lock.Unlock()
if componentFactory == nil {
componentFactory = &ComponentFactory{}
fmt.Println("ComponentFactory single instance...")
}
}
return componentFactory
}
func (*ComponentFactory) Instanceof(compName int) FlowComponent {
switch compName {
case HostCompletionComponentName:
return GetHostCompletionComponentInstance()
case DetectionSaverName:
return GetDetectionSaverComponentInstance()
default:
return GetEmptyInstance()
}
}
var componentMap = map[string]FlowComponent {}
func (*ComponentFactory) Init() {
hcc := GetHostCompletionComponentInstance()
componentMap[hcc.GetName()] = hcc
saver := GetDetectionSaverComponentInstance()
componentMap[saver.GetName()] = saver
}
func (*ComponentFactory) GetByName(name string) FlowComponent {
return componentMap[name]
}
func MapValue(ints []int, f func(i int) FlowComponent) []FlowComponent {
result := make([]FlowComponent, len(ints))
for i, v := range ints {
result[i] = f(v)
}
return result
}
func Exec(components []FlowComponent, ctx *Context) (err error) {
for _, comp := range components {
res, err := comp.Process(ctx)
if err != nil {
fmt.Println(err)
return err
}
if res.Code == define.TERMINAL {
panic("Flow terminated")
}
}
return nil
}
main.go
package main
import (
"fmt"
"github.com/qt/eventflow/pkg/compos"
"github.com/qt/eventflow/pkg/define"
"github.com/qt/eventflow/pkg/yaml"
"reflect"
)
func main() {
//testBasic()
testComponentExecution()
}
func testBasic() {
testPublicMemberConstruct()
testPrivateMemberConstruct()
testFactoryMethod()
testEmptyObject()
testSingleton()
testClassMethod()
testReadYaml()
}
func testPublicMemberConstruct() {
result := &define.FlowResult{ 200 }
fmt.Println(result)
fmt.Println(reflect.TypeOf(result))
}
func testPrivateMemberConstruct() {
//agent := &compos.AgentDetection{ "eventId", "agentId", 1 }
//error: implicit assignment of unexported field 'eventId' in compos.AgentDetection literal
empty := compos.AgentDetection{}
fmt.Println(empty)
fmt.Println(reflect.TypeOf(empty))
detection := compos.AgentDetection{}.Instanceof("agentId", 1)
fmt.Printf("d: %v\n", detection)
detection2 := compos.AgentDetection{}.InstanceByNaming("agentId", 1)
fmt.Printf("d2: %v\n", detection2)
fmt.Println("eventId: " + detection2.GetEventId())
detection3 := compos.NewAgentDetection("agentId", 1)
fmt.Printf("d3: %v\n", detection3)
}
func testFactoryMethod() {
adf := compos.GetAgentFactoryInstance()
detection := adf.Instanceof("agentId", 2)
fmt.Printf( "detection from factory method: %v\n", detection)
}
func testEmptyObject() {
var emp compos.AgentDetection
p1 := &emp
demp := emp.Instanceof("agentId", 1)
fmt.Printf("demp: %v\n", demp)
fmt.Println(emp)
fmt.Println(reflect.TypeOf(emp))
var emp2 compos.AgentDetection
p2 := &emp2
fmt.Println("compare reference to empty agentDetection")
compareObj(emp, emp2)
fmt.Println("compare pointers to empty agentDetection")
compareAgentDetection(p1, p2)
emp3 := &compos.AgentDetection{}
emp4 := &compos.AgentDetection{}
fmt.Println("compare pointers to empty2 agentDetection")
compareAgentDetection(emp3, emp4)
}
func compareObj(o1 interface{}, o2 interface{}) {
fmt.Printf("o1: %v\n", o1)
fmt.Printf("o2: %v\n", o2)
fmt.Printf("o1-p: %p\n", o1)
fmt.Printf("o2-p: %p\n", o2)
fmt.Printf("&o1: %v\n", &o1)
fmt.Printf("&o2: %v\n", &o2)
fmt.Printf("o1 == o2: %v\n", (o1 == o2))
fmt.Printf("&o1 == &o2: %v\n", &o1 == &o2)
}
func compareAgentDetection(adp1 *compos.AgentDetection, adp2 *compos.AgentDetection) {
fmt.Printf("adp1: %v\n", adp1)
fmt.Printf("adp2: %v\n", adp2)
fmt.Printf("adp1-p: %p\n", adp1)
fmt.Printf("adp2-p: %p\n", adp2)
fmt.Printf("*adp1: %v\n", *adp1)
fmt.Printf("*adp2: %v\n", *adp2)
fmt.Printf("&adp1: %v\n", &adp1)
fmt.Printf("&adp2: %v\n", &adp2)
fmt.Printf("adp1 == adp2: %v\n", (adp1 == adp2))
fmt.Printf("&adp1 == &adp2: %v\n", &adp1 == &adp2)
fmt.Printf("*adp1 == *adp2: %v\n", *adp1 == *adp2)
}
func testSingleton() {
adf := compos.GetAgentFactoryInstance()
adf2 := compos.GetAgentFactoryInstance()
compare(adf, adf2)
}
func compare(p1 *compos.AgentDetectionFactory, p2 *compos.AgentDetectionFactory) {
fmt.Printf("adf: %v\n", p1)
fmt.Printf("adf2: %v\n", p2)
fmt.Printf("adf-p: %p\n", p1)
fmt.Printf("adf2-p: %p\n", p2)
fmt.Printf("*adf: %v\n", *p1)
fmt.Printf("*adf2: %v\n", *p2)
fmt.Printf("&adf: %v\n", &p1)
fmt.Printf("&adf2: %v\n", &p2)
fmt.Printf("adf == adf2: %v\n", (p1 == p2))
fmt.Printf("&adf == &adf2: %v\n", &p1 == &p2)
fmt.Printf("*adf == *adf2: %v\n", *p1 == *p2)
}
func testClassMethod() {
withoutStar := compos.AgentDetection{}
ad := withoutStar.Instanceof("agentId111", 1)
fmt.Printf("ad: %v\n", ad)
withoutStar2 := &compos.AgentDetection{}
ad2 := withoutStar2.Instanceof("agentId222", 1)
fmt.Printf("ad: %v\n", ad2)
withStar := compos.AgentDetectionFactory{}
ad3 := withStar.Instanceof("agentId333", 1)
fmt.Printf("ad3: %v\n", ad3)
withStar2 := &compos.AgentDetectionFactory{}
ad4 := withStar2.Instanceof("agentId444", 1)
fmt.Printf("ad4: %v\n", ad4)
}
func testReadYaml() {
yaml.ReadYaml()
}
func testComponentExecution() {
//ctx := &compos.Context{ &event } //Cannot assign a value to the unexported field 'event'
detection := compos.AgentDetection{}.Instanceof("agentId", 1)
var event define.EventData = detection
ctx := compos.Context{}.New(&event)
cf := compos.GetComponentFactoryInstance()
cf.Init()
ch := make(chan int, 4)
defer close(ch)
go func() {
ch <- 0
ch <- 1
ch <- 2
ch <- 3
ch <- -1
}()
for {
select {
case msg := <- ch:
if (msg == 0) {
execDirect(ctx)
}
if (msg == 1) {
execRange(ctx)
}
if (msg == 2) {
execRange2(ctx, cf)
}
if (msg == 3) {
execByArrange(ctx, cf)
}
if (msg == -1) {
return
}
}
}
}
func execDirect(ctx *compos.Context) {
fmt.Println("execDirect")
fc := &compos.HostCompletionComponent{}
saver := &compos.DetectionSaver{}
fc.Process(ctx)
saver.Process(ctx)
}
func execRange(ctx *compos.Context) {
fmt.Println("execRange")
components := [...]compos.FlowComponent{&compos.HostCompletionComponent{}, &compos.DetectionSaver{} }
for _, comp := range components {
res, err := comp.Process(ctx)
if err != nil {
fmt.Println(err)
}
if res.Code == define.TERMINAL {
panic("Flow terminated")
}
}
}
func execRange2(ctx *compos.Context, cf *compos.ComponentFactory) {
fmt.Println("execRange2")
components := compos.MapValue([]int { compos.HostCompletionComponentName, compos.DetectionSaverName}, cf.Instanceof)
compos.Exec(components, ctx)
}
func execByArrange(ctx *compos.Context, cf *compos.ComponentFactory) {
fmt.Println("execByArrange")
flow := yaml.Read("./configs/eventflow.yml")
components := make([]compos.FlowComponent, 2)
for _, f := range flow.Flows {
fmt.Println(f.BizTypes)
for i, c := range f.ComponentConfigs {
if trueComp := cf.GetByName(c.Name) ; trueComp != nil {
components[i] = trueComp
}
}
}
compos.Exec(components, ctx)
}
readyaml.go
package yaml
import (
"fmt"
"gopkg.in/yaml.v3"
"io/ioutil"
"log"
)
type CommonConfig struct {
eventType string `yaml:"eventType"`
EventSourceType string `yaml:"eventSourceType"`
Model string `yaml:"model"`
Way string `yaml:"way"`
OriginParamType string `yaml:"originParamType"`
BuilderType string `yaml:"builderType"`
ComponentParamType string `yaml:"componentParamType"`
}
type ComponentConfig struct {
Name string `yaml:"name"`
}
type Flow struct {
BizTypes []string `yaml:"bizTypes"`
CommonConfig CommonConfig `yaml:"commonConfig"`
ComponentConfigs []ComponentConfig `yaml:"componentConfigs"`
}
type EventFlow struct {
Version string `yaml:"version"`
Flows []Flow `yaml:"flows"`
}
func Read(filename string) EventFlow {
ef := EventFlow{}
yamlFile, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Println(err.Error())
}
//fmt.Println(string(yamlFile))
err2 := yaml.Unmarshal(yamlFile, &ef)
if err2 != nil {
log.Fatalf("error: %v", err2)
}
return ef
}
func ReadYaml() {
ef := Read("./configs/eventflow.yml")
fmt.Println(ef)
for _, f := range ef.Flows {
fmt.Println(f.BizTypes)
fmt.Println(f.CommonConfig)
for _, c := range f.ComponentConfigs {
fmt.Println(c.Name)
}
}
}
eventflow.yaml
version: 1.0
flows:
- bizTypes:
- 'common'
commonConfig:
eventType: 'create'
eventSourceType: 'agent_event'
model: 'EVENTFLOW'
way: 'SERIAL'
originParamType: 'compos.AgentDetection'
builderType: 'compos.ContextBuilder'
componentParamType: 'compos.Context'
componentConfigs:
- name: 'compos.HostCompletionComponent'
- name: 'compos.DetectionSaver'