Apply .gitignore rules
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
package signalMgr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"Framework/exitMgr"
|
||||
"Framework/goroutineMgr"
|
||||
"Framework/reloadMgr"
|
||||
"goutil/debugUtil"
|
||||
"goutil/logUtil"
|
||||
)
|
||||
|
||||
// Start ...启动信号管理器
|
||||
func Start() {
|
||||
go func() {
|
||||
goroutineName := "signalMgr.Start"
|
||||
goroutineMgr.Monitor(goroutineName)
|
||||
defer goroutineMgr.ReleaseMonitor(goroutineName)
|
||||
|
||||
sigs := make(chan os.Signal)
|
||||
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP)
|
||||
|
||||
for {
|
||||
// 准备接收信息
|
||||
sig := <-sigs
|
||||
|
||||
// 输出信号
|
||||
debugUtil.Println("sig:", sig)
|
||||
|
||||
if sig == syscall.SIGHUP {
|
||||
logUtil.InfoLog("收到重启的信号,准备重新加载配置")
|
||||
|
||||
// 重新加载
|
||||
errList := reloadMgr.Reload()
|
||||
for _, err := range errList {
|
||||
logUtil.ErrorLog(fmt.Sprintf("重启失败,错误信息为:%s", err))
|
||||
}
|
||||
|
||||
logUtil.InfoLog("收到重启的信号,重新加载配置完成")
|
||||
} else {
|
||||
logUtil.InfoLog("收到退出程序的信号,开始退出……")
|
||||
|
||||
// 调用退出的方法
|
||||
exitMgr.Exit()
|
||||
|
||||
logUtil.InfoLog("收到退出程序的信号,退出完成……")
|
||||
|
||||
// 一旦收到信号,则表明管理员希望退出程序,则先保存信息,然后退出
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package mysqlSync
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"Framework/dataSyncMgr/mysqlSync/logSqlSync"
|
||||
"Framework/dataSyncMgr/mysqlSync/sqlSync"
|
||||
"goutil/debugUtil"
|
||||
"goutil/logUtil"
|
||||
)
|
||||
|
||||
// 数据同步管理
|
||||
type SyncMgr struct {
|
||||
// 服务器组Id
|
||||
serverGroupId int32
|
||||
|
||||
// 同步数据的存储路径
|
||||
dirPath string
|
||||
|
||||
// 大文件对象size
|
||||
maxFileSize int
|
||||
|
||||
// 数据库对象
|
||||
dbObj *sql.DB
|
||||
|
||||
// 同步对象集合
|
||||
syncObjMap map[string]*sqlSync.SyncObject
|
||||
|
||||
// 同步对象锁
|
||||
mutex sync.RWMutex
|
||||
|
||||
// 新建实例对象的函数
|
||||
newInstanceFunc func(mgr *SyncMgr, identifier string) *sqlSync.SyncObject
|
||||
}
|
||||
|
||||
// 注册同步对象
|
||||
// identifier:当前数据的唯一标识(可以使用数据库表名)
|
||||
func (this *SyncMgr) RegisterSyncObj(identifier string) {
|
||||
this.mutex.Lock()
|
||||
defer this.mutex.Unlock()
|
||||
|
||||
// 判断是否设置了相同的唯一标识,以免弄混淆
|
||||
if _, exists := this.syncObjMap[identifier]; exists {
|
||||
prefix := fmt.Sprintf("%s-%s", identifier, "SyncMgr.RegisterSyncObj")
|
||||
err := fmt.Errorf("%s has already existed, please change another identifier", prefix)
|
||||
logUtil.ErrorLog(err.Error())
|
||||
panic(err)
|
||||
}
|
||||
|
||||
syncObj := this.newInstanceFunc(this, identifier)
|
||||
syncObj.Init(this.maxFileSize)
|
||||
this.syncObjMap[identifier] = syncObj
|
||||
|
||||
if debugUtil.IsDebug() {
|
||||
fmt.Printf("%s同步对象成功注册进SyncMgr, 当前有%d个同步对象\n", identifier, len(this.syncObjMap))
|
||||
}
|
||||
}
|
||||
|
||||
// 保存数据
|
||||
// identifier:当前数据的唯一标识(可以使用数据库表名)
|
||||
// command:sql命令
|
||||
func (this *SyncMgr) Save(identifier string, command string) {
|
||||
this.mutex.RLock()
|
||||
defer this.mutex.RUnlock()
|
||||
|
||||
syncObj, exists := this.syncObjMap[identifier]
|
||||
if !exists {
|
||||
err := fmt.Errorf("syncObj:%s does not existed, please register first", identifier)
|
||||
logUtil.ErrorLog(err.Error())
|
||||
panic(err)
|
||||
}
|
||||
|
||||
syncObj.Save(command)
|
||||
}
|
||||
|
||||
// 构造同步管理对象
|
||||
// serverGroupId:服务器组Id
|
||||
// dirPath: 文件目录
|
||||
// maxFileSize: 大文件对象大小
|
||||
// survivalTime: 同步数据存活时间 (单位:hour)
|
||||
// dbObj: 数据库对象
|
||||
func NewSyncMgr(serverGroupId int32, dirPath string, maxFileSize int, survivalTime int, dbObj *sql.DB) *SyncMgr {
|
||||
result := &SyncMgr{
|
||||
serverGroupId: serverGroupId,
|
||||
dirPath: dirPath,
|
||||
maxFileSize: maxFileSize,
|
||||
dbObj: dbObj,
|
||||
syncObjMap: make(map[string]*sqlSync.SyncObject),
|
||||
newInstanceFunc: func(mgr *SyncMgr, identifier string) *sqlSync.SyncObject {
|
||||
handler := newSyncObject(mgr.dirPath, identifier, mgr.dbObj)
|
||||
return sqlSync.NewSyncObject(mgr.dirPath, identifier, mgr.dbObj, handler)
|
||||
},
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// 新建日志同步管理对象
|
||||
// serverGroupId:服务器组Id
|
||||
// dirPath: 文件目录
|
||||
// maxFileSize: 大文件对象大小
|
||||
// dbObj: 数据库对象
|
||||
func NewLogSyncMgr(serverGroupId int32, dirPath string, maxFileSize int, dbObj *sql.DB) *SyncMgr {
|
||||
result := &SyncMgr{
|
||||
serverGroupId: serverGroupId,
|
||||
dirPath: dirPath,
|
||||
maxFileSize: maxFileSize,
|
||||
dbObj: dbObj,
|
||||
syncObjMap: make(map[string]*sqlSync.SyncObject),
|
||||
newInstanceFunc: func(mgr *SyncMgr, identifier string) *sqlSync.SyncObject {
|
||||
handler := logSqlSync.NewSyncObject(mgr.serverGroupId, mgr.dirPath, identifier, mgr.dbObj)
|
||||
return sqlSync.NewSyncObject(mgr.dirPath, identifier, mgr.dbObj, handler)
|
||||
},
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
redisUtil对Redis的连接池进行了一定程度的封装
|
||||
将常用的方法进行了内部封装,对于不常见的方法,有两种处理方式:
|
||||
1、向作者提出请求,由作者添加到代码中
|
||||
2、调用GetConnection方法,然后自己实现逻辑
|
||||
在代码中,统一将conn.Do的结果和redis.Int,redis.String等类型转换合并处理
|
||||
|
||||
redis的命令请参考:https://redis.readthedocs.io/en/2.6/index.html
|
||||
*/
|
||||
package redisUtil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gomodule/redigo/redis"
|
||||
)
|
||||
|
||||
// 自定义Redis连接池对象
|
||||
type RedisPool struct {
|
||||
name string
|
||||
address string
|
||||
pool *redis.Pool
|
||||
}
|
||||
|
||||
// 获取自定义Redis连接池对象的名称
|
||||
// 返回值:
|
||||
// 自定义Redis连接池对象的名称
|
||||
func (this *RedisPool) GetName() string {
|
||||
return this.name
|
||||
}
|
||||
|
||||
// 获取自定义Redis连接池对象的目标地址
|
||||
// 返回值:
|
||||
// 自定义Redis连接池对象的目标地址
|
||||
func (this *RedisPool) GetAddress() string {
|
||||
return this.address
|
||||
}
|
||||
|
||||
// 从自定义连接池中获取连接,在使用后需要调用Close方法
|
||||
// 返回值:
|
||||
// 连接对象
|
||||
func (this *RedisPool) GetConnection() redis.Conn {
|
||||
return this.pool.Get()
|
||||
}
|
||||
|
||||
// 关闭自定义连接池
|
||||
func (this *RedisPool) Close() {
|
||||
this.pool.Close()
|
||||
}
|
||||
|
||||
// 测试连接情况
|
||||
// 返回值:
|
||||
// 错误对象
|
||||
func (this *RedisPool) TestConnection() error {
|
||||
conn := this.GetConnection()
|
||||
defer conn.Close()
|
||||
|
||||
_, err := conn.Do("PING")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建新的Redis连接池对象(obsolete,建议使用NewRedisPool2)
|
||||
// name:连接池对象名称
|
||||
// connectionString:Redis服务器连接地址
|
||||
// password:Redis服务器连接密码
|
||||
// database:Redis服务器选择的数据库
|
||||
// maxActive:Redis连接池允许的最大活跃连接数量
|
||||
// maxIdle:Redis连接池允许的最大空闲数量
|
||||
// idleTimeout:连接被回收前的空闲时间
|
||||
// dialConnectTimeout:连接Redis服务器超时时间
|
||||
// 返回值:
|
||||
// Redis连接池对象
|
||||
func NewRedisPool(name, connectionString, password string, database, maxActive, maxIdle int, idleTimeout, dialConnectTimeout time.Duration) *RedisPool {
|
||||
redisConfig := NewRedisConfig2(connectionString, password, database, maxActive, maxIdle, idleTimeout, dialConnectTimeout)
|
||||
return NewRedisPool2(name, redisConfig)
|
||||
}
|
||||
|
||||
// 创建新的Redis连接池对象
|
||||
// name:连接池对象名称
|
||||
// redisConfig:Redis配置对象
|
||||
// 返回值:
|
||||
// Redis连接池对象
|
||||
func NewRedisPool2(name string, redisConfig *RedisConfig) *RedisPool {
|
||||
poolObj := &redis.Pool{
|
||||
MaxActive: redisConfig.MaxActive,
|
||||
MaxIdle: redisConfig.MaxIdle,
|
||||
IdleTimeout: redisConfig.IdleTimeout,
|
||||
Dial: func() (redis.Conn, error) {
|
||||
options := make([]redis.DialOption, 0, 4)
|
||||
options = append(options, redis.DialConnectTimeout(redisConfig.DialConnectTimeout))
|
||||
options = append(options, redis.DialDatabase(redisConfig.Database))
|
||||
if redisConfig.Password != "" {
|
||||
options = append(options, redis.DialPassword(redisConfig.Password))
|
||||
}
|
||||
|
||||
conn, err := redis.Dial("tcp", redisConfig.ConnectionString, options...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Dial failed, err:%s", err)
|
||||
}
|
||||
|
||||
return conn, err
|
||||
},
|
||||
TestOnBorrow: func(conn redis.Conn, t time.Time) error {
|
||||
if time.Since(t) < time.Minute {
|
||||
return nil
|
||||
}
|
||||
_, err := conn.Do("PING")
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
return &RedisPool{
|
||||
name: name,
|
||||
address: redisConfig.ConnectionString,
|
||||
pool: poolObj,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package ensureSendUtil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"goutil/fileUtil"
|
||||
"goutil/logUtil"
|
||||
"goutil/stringUtil"
|
||||
)
|
||||
|
||||
// 从目录加载缓存数据并发送
|
||||
func loadData(s EnsureSender, folder string) error {
|
||||
if fileList, err := fileUtil.GetFileList(folder); err != nil {
|
||||
return err
|
||||
} else {
|
||||
for _, filename := range fileList {
|
||||
// 读取发送内容
|
||||
if fileContent, err := fileUtil.ReadFileContent(filename); err != nil {
|
||||
// 打印错误
|
||||
log := fmt.Sprintf("ensureSendUtil.loadData: Failed To Read File: %s %s\n", err, filename)
|
||||
logUtil.NormalLog(log, logUtil.Error)
|
||||
} else if err = fileUtil.DeleteFile(filename); err != nil {
|
||||
// 删除文件,如果成功则将内容添加到通道中,否则不处理
|
||||
log := fmt.Sprintf("ensureSendUtil.loadData: Failed To Delete File: %s %s", err, filename)
|
||||
logUtil.NormalLog(log, logUtil.Error)
|
||||
} else {
|
||||
// 发送数据
|
||||
s.Write(fileContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 保存数据到文件中(通常在退出时调用)
|
||||
func saveData(datas <-chan dataItem, folder string) (failed []dataItem, err error) {
|
||||
defer func() {
|
||||
if len(failed) > 0 {
|
||||
err = fmt.Errorf("保存数据时有%d个失败数据", len(failed))
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case v := <-datas:
|
||||
filename := stringUtil.GetNewGUID()
|
||||
if e := fileUtil.WriteFile(folder, filename, false, v.String()); e != nil {
|
||||
failed = append(failed, v)
|
||||
log := fmt.Sprintf("ensureSendUtil.saveData: 写入错误\n目录:%s,文件:%s,错误信息为:%s, Data:%s",
|
||||
folder, filename, err, v.String())
|
||||
logUtil.NormalLog(log, logUtil.Error)
|
||||
}
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
package configUtil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"goutil/xmlUtil"
|
||||
)
|
||||
|
||||
// bool值读取测试
|
||||
func TestBool(t *testing.T) {
|
||||
xmlConfigData, errMsg := getxmlConfigData()
|
||||
if errMsg != nil {
|
||||
t.Error(errMsg)
|
||||
t.Fail()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var ispost bool
|
||||
ispost, errMsg = xmlConfigData.Bool("html/body", "IsPost")
|
||||
if errMsg != nil {
|
||||
t.Error(errMsg)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
fmt.Println("读取到的值:", ispost)
|
||||
if ispost == false {
|
||||
t.Error("html/body的isPost读取错误")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
ispost = xmlConfigData.DefaultBool("html/body", "IsPost", false)
|
||||
if ispost == false {
|
||||
t.Error("html/body的isPost读取错误")
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
// int值读取测试
|
||||
func TestInt(t *testing.T) {
|
||||
xmlConfigData, errMsg := getxmlConfigData()
|
||||
if errMsg != nil {
|
||||
t.Error(errMsg)
|
||||
t.Fail()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var id int
|
||||
id, errMsg = xmlConfigData.Int("html/body/ul/li/a[@id=1]", "id")
|
||||
if errMsg != nil {
|
||||
t.Error(errMsg)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
if id != 1 {
|
||||
t.Errorf("html/body的isPost读取错误,读取到的值:%v", id)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
id = xmlConfigData.DefaultInt("html/body", "id", 2)
|
||||
if id != 2 {
|
||||
t.Error("TestInt html/body的id读取错误")
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
// int64值读取测试
|
||||
func TestInt64(t *testing.T) {
|
||||
xmlConfigData, errMsg := getxmlConfigData()
|
||||
if errMsg != nil {
|
||||
t.Error(errMsg)
|
||||
t.Fail()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var id int64
|
||||
id, errMsg = xmlConfigData.Int64("html/body/ul/li/a[@id=1]", "id")
|
||||
if errMsg != nil {
|
||||
t.Error(errMsg)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
if id != 1 {
|
||||
t.Errorf("TestInt64 html/body/ul/li/a[@id=1]的id读取错误,读取到的值:%v", id)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
id = xmlConfigData.DefaultInt64("html/body", "id", 2)
|
||||
if id != 2 {
|
||||
t.Error("TestInt64 html/body的id读取错误")
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
// Float值读取测试
|
||||
func TestFloat(t *testing.T) {
|
||||
xmlConfigData, errMsg := getxmlConfigData()
|
||||
if errMsg != nil {
|
||||
t.Error(errMsg)
|
||||
t.Fail()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var id float64
|
||||
id, errMsg = xmlConfigData.Float("html/body/ul/li/a[@id=1]", "dd")
|
||||
if errMsg != nil {
|
||||
t.Error(errMsg)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
if id != 1.1 {
|
||||
t.Errorf("TestFloat html/body/ul/li/a[@id=1]的id读取错误,读取到的值:%v", id)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
id = xmlConfigData.DefaultFloat("html/body", "id", 2)
|
||||
if id != 2 {
|
||||
t.Error("TestFloat html/body的id读取错误")
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
// 字符串读取测试
|
||||
func TestString(t *testing.T) {
|
||||
xmlConfigData, errMsg := getxmlConfigData()
|
||||
if errMsg != nil {
|
||||
t.Error(errMsg)
|
||||
t.Fail()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var id string
|
||||
id, errMsg = xmlConfigData.String("html/body/ul/li/a[@id=1]", "dd")
|
||||
if errMsg != nil {
|
||||
t.Error(errMsg)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
if id != "1.1" {
|
||||
t.Errorf("TestString html/body/ul/li/a[@id=1]的id读取错误,读取到的值:%v", id)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
id = xmlConfigData.DefaultString("html/body", "id", "2")
|
||||
if id != "2" {
|
||||
t.Error("TestString html/body的id读取错误")
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
type HelloStruct struct {
|
||||
// 连接字符串
|
||||
ConnectionString string
|
||||
|
||||
// 最大开启连接数量
|
||||
MaxOpenConns int `xml:",attr"`
|
||||
|
||||
// 最大空闲连接数量
|
||||
MaxIdleConns int `xml:",attr"`
|
||||
}
|
||||
|
||||
func (this *HelloStruct) Equal(other *HelloStruct) bool {
|
||||
return this.MaxOpenConns == other.MaxOpenConns && this.MaxIdleConns == other.MaxIdleConns
|
||||
}
|
||||
|
||||
func TestUnmarshal(t *testing.T) {
|
||||
data, _ := getxmlConfigData2(`
|
||||
<DBConnection>
|
||||
<GameServerCenterDB MaxOpenConns="10" MaxIdleConns="5">
|
||||
<![CDATA[
|
||||
root:moqikaka3312@tcp(10.1.0.10:3312)/2_gsc_develop?charset=utf8&parseTime=true&loc=Local&timeout=60s
|
||||
]]>
|
||||
</GameServerCenterDB>
|
||||
</DBConnection>
|
||||
`)
|
||||
|
||||
val := &HelloStruct{}
|
||||
err := data.Unmarshal("/DBConnection/GameServerCenterDB", val)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := &HelloStruct{
|
||||
ConnectionString: "root:moqikaka3312@tcp(10.1.0.10:3312)/2_gsc_develop?charset=utf8&parseTime=true&loc=Local&timeout=60s",
|
||||
MaxOpenConns: 10,
|
||||
MaxIdleConns: 5,
|
||||
}
|
||||
if want.Equal(val) == false {
|
||||
t.Errorf("Expected %v, but now got %v", want, val)
|
||||
}
|
||||
}
|
||||
|
||||
type ConnsNum int
|
||||
type Hello2Struct struct {
|
||||
// 连接字符串
|
||||
ConnectionString string
|
||||
|
||||
// 最大开启连接数量
|
||||
MaxOpenConns ConnsNum
|
||||
|
||||
// 最大空闲连接数量
|
||||
MaxIdleConns ConnsNum
|
||||
}
|
||||
|
||||
func (this *Hello2Struct) Equal(other *Hello2Struct) bool {
|
||||
return this.MaxOpenConns == other.MaxOpenConns && this.MaxIdleConns == other.MaxIdleConns
|
||||
}
|
||||
|
||||
func TestUnmarshal2(t *testing.T) {
|
||||
data, _ := getxmlConfigData2(`
|
||||
<DBConnection>
|
||||
<GameServerCenterDB MaxOpenConns="10" MaxIdleConns="5">
|
||||
<![CDATA[
|
||||
root:moqikaka3312@tcp(10.1.0.10:3312)/2_gsc_develop?charset=utf8&parseTime=true&loc=Local&timeout=60s
|
||||
]]>
|
||||
</GameServerCenterDB>
|
||||
</DBConnection>
|
||||
`)
|
||||
|
||||
val := &Hello2Struct{}
|
||||
err := data.Unmarshal("/DBConnection/GameServerCenterDB", val)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := &Hello2Struct{
|
||||
ConnectionString: "root:moqikaka3312@tcp(10.1.0.10:3312)/2_gsc_develop?charset=utf8&parseTime=true&loc=Local&timeout=60s",
|
||||
MaxOpenConns: 10,
|
||||
MaxIdleConns: 5,
|
||||
}
|
||||
if want.Equal(val) == false {
|
||||
t.Errorf("Expected %v, but now got %v", want, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshal3(t *testing.T) {
|
||||
data, _ := getxmlConfigData2(`
|
||||
<DBConnection>
|
||||
<GameServerCenterDB MaxOpenConns="10">
|
||||
<![CDATA[
|
||||
root:moqikaka3312@tcp(10.1.0.10:3312)/2_gsc_develop?charset=utf8&parseTime=true&loc=Local&timeout=60s
|
||||
]]>
|
||||
</GameServerCenterDB>
|
||||
</DBConnection>
|
||||
`)
|
||||
|
||||
val := &HelloStruct{}
|
||||
err := data.Unmarshal("/DBConnection/GameServerCenterDB", val)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := &HelloStruct{
|
||||
ConnectionString: "root:moqikaka3312@tcp(10.1.0.10:3312)/2_gsc_develop?charset=utf8&parseTime=true&loc=Local&timeout=60s",
|
||||
MaxOpenConns: 10,
|
||||
MaxIdleConns: 0,
|
||||
}
|
||||
if want.Equal(val) == false {
|
||||
t.Errorf("Expected %v, but now got %v", want, val)
|
||||
}
|
||||
}
|
||||
|
||||
func getxmlConfigData() (xmlConfigData *XmlConfig, errMsg error) {
|
||||
content := `
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Hello</title>
|
||||
<meta name="language" content="en"/>
|
||||
</head>
|
||||
<body IsPost='true'>
|
||||
<h1> This is a H1 </h1>
|
||||
<ul>
|
||||
<li><a id="1" dd='1.1' href="/">Home</a></li>
|
||||
<li><a id="2" href="/about">about</a></li>
|
||||
<li><a id="3" href="/account">login</a></li>
|
||||
<li></li>
|
||||
</ul>
|
||||
<p>
|
||||
Hello,This is an example for gxpath.
|
||||
</p>
|
||||
<footer>footer script</footer>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
var root *xmlUtil.Node
|
||||
root, errMsg = xmlUtil.LoadFromString(content)
|
||||
if errMsg == nil {
|
||||
xmlConfigData = NewXmlConfig()
|
||||
xmlConfigData.LoadFromXmlNode(root)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getxmlConfigData2(xml string) (xmlConfigData *XmlConfig, errMsg error) {
|
||||
var root *xmlUtil.Node
|
||||
root, errMsg = xmlUtil.LoadFromString(xml)
|
||||
if errMsg == nil {
|
||||
xmlConfigData = NewXmlConfig()
|
||||
xmlConfigData.LoadFromXmlNode(root)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user