golang操作Redis&Mysql&RabbitMQ:
Reids
安裝導(dǎo)入
go?get?github.com/garyburd/redigo/redis
import?"github.com/garyburd/redigo/redis"
使用
連接
import?"github.com/garyburd/redigo/redis"
func?main()?{
c,?err?:=?redis.Dial("tcp",?"localhost:6379")
if?err?!=?nil?{
fmt.Println("conn?redis?failed,?err:",?err)
return
}
defer?c.Close()
}
set & get
_,?err?=?c.Do("Set",?"name",?"nick")
if?err?!=?nil?{
fmt.Println(err)
return
}
r,?err?:=?redis.String(c.Do("Get",?"name"))
if?err?!=?nil?{
fmt.Println(err)
return
}
fmt.Println(r)
mset & mget
批量設(shè)置
_,?err?=?c.Do("MSet",?"name",?"nick",?"age",?"18")
if?err?!=?nil?{
fmt.Println("MSet?error:?",?err)
return
}
r2,?err?:=?redis.Strings(c.Do("MGet",?"name",?"age"))
if?err?!=?nil?{
fmt.Println("MGet?error:?",?err)
return
}
fmt.Println(r2)
hset & hget
hash操作
_,?err?=?c.Do("HSet",?"names",?"nick",?"suoning")
if?err?!=?nil?{
fmt.Println("hset?error:?",?err)
return
}
r,?err?=?redis.String(c.Do("HGet",?"names",?"nick"))
if?err?!=?nil?{
fmt.Println("hget?error:?",?err)
return
}
fmt.Println(r)
expire
設(shè)置過期時間
_,?err?=?c.Do("expire",?"names",?5)
if?err?!=?nil?{
fmt.Println("expire?error:?",?err)
return
}
lpush & lpop & llen
隊列
//?隊列
_,?err?=?c.Do("lpush",?"Queue",?"nick",?"dawn",?9)
if?err?!=?nil?{
fmt.Println("lpush?error:?",?err)
return
}
for?{
r,?err?=?redis.String(c.Do("lpop",?"Queue"))
if?err?!=?nil?{
fmt.Println("lpop?error:?",?err)
break
}
fmt.Println(r)
}
r3,?err?:=?redis.Int(c.Do("llen",?"Queue"))
if?err?!=?nil?{
fmt.Println("llen?error:?",?err)
return
}
連接池
各參數(shù)的解釋如下:
MaxIdle:最大的空閑連接數(shù),表示即使沒有redis連接時依然可以保持N個空閑的連接,而不被清除,隨時處于待命狀態(tài)酌心。
MaxActive:最大的激活連接數(shù),表示同時最多有N個連接
IdleTimeout:最大的空閑連接等待時間逸绎,超過此時間后饮笛,空閑連接將被關(guān)閉
pool?:=?&redis.Pool{
MaxIdle:?????16,
MaxActive:???1024,
IdleTimeout:?300,
Dial:?func()?(redis.Conn,?error)?{
return?redis.Dial("tcp",?"localhost:6379")
},
}
連接池例子:
package?main
import?(
"fmt"
"github.com/garyburd/redigo/redis"
)
var?pool?*redis.Pool
func?init()?{
pool?=?&redis.Pool{
MaxIdle:?????16,
MaxActive:???1024,
IdleTimeout:?300,
Dial:?func()?(redis.Conn,?error)?{
return?redis.Dial("tcp",?"localhost:6379")
},
}
}
func?main()?{
c?:=?pool.Get()
defer?c.Close()
_,?err?:=?c.Do("Set",?"name",?"nick")
if?err?!=?nil?{
fmt.Println(err)
return
}
r,?err?:=?redis.String(c.Do("Get",?"name"))
if?err?!=?nil?{
fmt.Println(err)
return
}
fmt.Println(r)
}
管道操作
請求/響應(yīng)服務(wù)可以實現(xiàn)持續(xù)處理新請求蹄梢,客戶端可以發(fā)送多個命令到服務(wù)器而無需等待響應(yīng)稽亏,最后在一次讀取多個響應(yīng)壶冒。
使用Send(),F(xiàn)lush()截歉,Receive()方法支持管道化操作
Send向連接的輸出緩沖中寫入命令胖腾。
Flush將連接的輸出緩沖清空并寫入服務(wù)器端。
Recevie按照FIFO順序依次讀取服務(wù)器的響應(yīng)瘪松。
func?main()?{
c,?err?:=?redis.Dial("tcp",?"localhost:6379")
if?err?!=?nil?{
fmt.Println("conn?redis?failed,?err:",?err)
return
}
defer?c.Close()
c.Send("SET",?"name1",?"sss1")
c.Send("SET",?"name2",?"sss2")
c.Flush()
v,?err?:=?c.Receive()
fmt.Printf("v:%v,err:%v\n",?v,?err)
v,?err?=?c.Receive()
fmt.Printf("v:%v,err:%v\n",?v,?err)
v,?err?=?c.Receive()????//?夯住咸作,一直等待
fmt.Printf("v:%v,err:%v\n",?v,?err)
}
Mysql
安裝導(dǎo)入
go?get?"github.com/go-sql-driver/mysql"
go?get?"github.com/jmoiron/sqlx"
import?(
_?"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
連接
import?(
_?"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
var?Db?*sqlx.DB
func?init()?{
database,?err?:=?sqlx.Open("mysql",?"root:@tcp(127.0.0.1:3306)/test")
if?err?!=?nil?{
fmt.Println("open?mysql?failed,",?err)
return
}
Db?=?database
}
建表
CREATE?TABLE?`person`?(
`user_id`?int(128)?DEFAULT?NULL,
`username`?varchar(255)?DEFAULT?NULL,
`sex`?varchar(16)?DEFAULT?NULL,
`email`?varchar(128)?DEFAULT?NULL
)?ENGINE=InnoDB?DEFAULT?CHARSET=utf8
(insert)
package?main
import?(
"fmt"
_?"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
type?Person?struct?{
UserId???int????`db:"user_id"`
Username?string?`db:"username"`
Sex??????string?`db:"sex"`
Email????string?`db:"email"`
}
var?Db?*sqlx.DB
func?init()?{
database,?err?:=?sqlx.Open("mysql",?"root:@tcp(127.0.0.1:3306)/test")
if?err?!=?nil?{
fmt.Println("open?mysql?failed,",?err)
return
}
Db?=?database
}
func?main()?{
r,?err?:=?Db.Exec("insert?into?person(username,?sex,?email)values(?,??,??)",?"suoning",?"man",?"suoning@net263.com")
if?err?!=?nil?{
fmt.Println("exec?failed,?",?err)
return
}
id,?err?:=?r.LastInsertId()
if?err?!=?nil?{
fmt.Println("exec?failed,?",?err)
return
}
fmt.Println("insert?succ:",?id)
}
(update)
package?main
import?(
"fmt"
_?"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
type?Person?struct?{
UserId???int????`db:"user_id"`
Username?string?`db:"username"`
Sex??????string?`db:"sex"`
Email????string?`db:"email"`
}
var?Db?*sqlx.DB
func?init()?{
database,?err?:=?sqlx.Open("mysql",?"root:@tcp(127.0.0.1:3306)/test")
if?err?!=?nil?{
fmt.Println("open?mysql?failed,",?err)
return
}
Db?=?database
}
func?main()?{
_,?err?:=?Db.Exec("update?person?set?user_id=??where?username=?",?20170808,?"suoning")
if?err?!=?nil?{
fmt.Println("exec?failed,?",?err)
return
}
}
(select)
package?main
import?(
"fmt"
_?"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
type?Person?struct?{
UserId???int????`db:"user_id"`
Username?string?`db:"username"`
Sex??????string?`db:"sex"`
Email????string?`db:"email"`
}
type?Place?struct?{
Country?string?`db:"country"`
City????string?`db:"city"`
TelCode?int????`db:"telcode"`
}
var?Db?*sqlx.DB
func?init()?{
database,?err?:=?sqlx.Open("mysql",?"root:@tcp(127.0.0.1:3306)/test")
if?err?!=?nil?{
fmt.Println("open?mysql?failed,",?err)
return
}
Db?=?database
}
func?main()?{
var?person?[]Person
err?:=?Db.Select(&person,?"select?user_id,?username,?sex,?email?from?person?where?user_id=?",?1)
if?err?!=?nil?{
fmt.Println("exec?failed,?",?err)
return
}
fmt.Println("select?succ:",?person)
people?:=?[]Person{}
Db.Select(&people,?"SELECT?*?FROM?person?ORDER?BY?user_id?ASC")
fmt.Println(people)
jason,?john?:=?people[0],?people[1]
fmt.Printf("%#v\n%#v",?jason,?john)
}
(delete)
package?main
import?(
"fmt"
_?"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
type?Person?struct?{
UserId???int????`db:"user_id"`
Username?string?`db:"username"`
Sex??????string?`db:"sex"`
Email????string?`db:"email"`
}
var?Db?*sqlx.DB
func?init()?{
database,?err?:=?sqlx.Open("mysql",?"root:@tcp(127.0.0.1:3306)/test")
if?err?!=?nil?{
fmt.Println("open?mysql?failed,",?err)
return
}
Db?=?database
}
func?main()?{
_,?err?:=?Db.Exec("delete?from?person?where?username=??limit?1",?"suoning")
if?err?!=?nil?{
fmt.Println("exec?failed,?",?err)
return
}
fmt.Println("delete?succ")
}
事務(wù)
package?main
import?(
"github.com/astaxie/beego/logs"
_?"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
var?Db?*sqlx.DB
func?init()?{
database,?err?:=?sqlx.Open("mysql",?"root:@tcp(127.0.0.1:3306)/test")
if?err?!=?nil?{
logs.Error("open?mysql?failed,",?err)
return
}
Db?=?database
}
func?main()??{
conn,?err?:=?Db.Begin()
if?err?!=?nil?{
logs.Warn("DB.Begin?failed,?err:%v",?err)
return
}
defer?func()?{
if?err?!=?nil?{
conn.Rollback()
return
}
conn.Commit()
}()
//?do?something
}
RabbitMQ
安裝
go?get?"github.com/streadway/amqp"
普通模式
生產(chǎn)者:
package?main
import?(????"fmt"
"log"
"os"
"strings"
"github.com/streadway/amqp"
"time")/*默認(rèn)點對點模式*/func?failOnError(err?error,?msg?string)?{????if?err?!=?nil?{
log.Fatalf("%s:?%s",?msg,?err)
panic(fmt.Sprintf("%s:?%s",?msg,?err))
}
}
func?main()?{????//?連接
conn,?err?:=?amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err,?"Failed?to?connect?to?RabbitMQ")
defer?conn.Close()????//?打開一個并發(fā)服務(wù)器通道來處理消息
ch,?err?:=?conn.Channel()
failOnError(err,?"Failed?to?open?a?channel")
defer?ch.Close()????//?申明一個隊列
q,?err?:=?ch.QueueDeclare(????????"task_queue",?//?name
true,?????????//?durable??持久性的,如果事前已經(jīng)聲明了該隊列,不能重復(fù)聲明
false,????????//?delete?when?unused
false,????????//?exclusive?如果是真宵睦,連接一斷開记罚,隊列刪除
false,????????//?no-wait
nil,??????????//?arguments????)
failOnError(err,?"Failed?to?declare?a?queue")
body?:=?bodyFrom(os.Args)????//?發(fā)布
err?=?ch.Publish(????????"",?????//?exchange?默認(rèn)模式,exchange為空
q.Name,???????????//?routing?key?默認(rèn)模式路由到同名隊列壳嚎,即是task_queue
false,??//?mandatory
false,
amqp.Publishing{????????????//?持久性的發(fā)布桐智,因為隊列被聲明為持久的末早,發(fā)布消息必須加上這個(可能不用),但消息還是可能會丟酵使,如消息到緩存但MQ掛了來不及持久化荐吉。????????????DeliveryMode:?amqp.Persistent,
ContentType:??"text/plain",
Body:?????????[]byte(body),
})
failOnError(err,?"Failed?to?publish?a?message")
log.Printf("?[x]?Sent?%s",?body)
}
func?bodyFrom(args?[]string)?string?{????var?s?string
if?(len(args)?<?2)?||?os.Args[1]?==?""?{
s?=?fmt.Sprintf("%s-%v","hello",?time.Now())
}?else?{
s?=?strings.Join(args[1:],?"?")
}????return?s
}
消費者:
package?main
import?(
"bytes"
"fmt"
"github.com/streadway/amqp"
"log"
"time"
)
/*
默認(rèn)點對點模式
工作方焙糟,多個嫡秕,拿發(fā)布方的消息
*/
func?failOnError(err?error,?msg?string)?{
if?err?!=?nil?{
log.Fatalf("%s:?%s",?msg,?err)
panic(fmt.Sprintf("%s:?%s",?msg,?err))
}
}
func?main()?{
conn,?err?:=?amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err,?"Failed?to?connect?to?RabbitMQ")
defer?conn.Close()
ch,?err?:=?conn.Channel()
failOnError(err,?"Failed?to?open?a?channel")
defer?ch.Close()
//?指定隊列岸浑!
q,?err?:=?ch.QueueDeclare(
"task_queue",?//?name
true,?????????//?durable
false,????????//?delete?when?unused
false,????????//?exclusive
false,????????//?no-wait
nil,??????????//?arguments
)
failOnError(err,?"Failed?to?declare?a?queue")
//?Fair?dispatch?預(yù)取,每個工作方每次拿一個消息,確認(rèn)后才拿下一次郊闯,緩解壓力
err?=?ch.Qos(
1,?????//?prefetch?count
0,?????//?prefetch?size
false,?//?global
)
failOnError(err,?"Failed?to?set?QoS")
//?消費根據(jù)隊列名
msgs,?err?:=?ch.Consume(
q.Name,?//?queue
"",?????//?consumer
false,??//?auto-ack???設(shè)置為真自動確認(rèn)消息
false,??//?exclusive
false,??//?no-local
false,??//?no-wait
nil,????//?args
)
failOnError(err,?"Failed?to?register?a?consumer")
forever?:=?make(chan?bool)
go?func()?{
for?d?:=?range?msgs?{
log.Printf("Received?a?message:?%s",?d.Body)
dot_count?:=?bytes.Count(d.Body,?[]byte("."))
t?:=?time.Duration(dot_count)
time.Sleep(t?*?time.Second)
log.Printf("Done")
//?確認(rèn)消息被收到!羹膳!如果為真的胖齐,那么同在一個channel,在該消息之前未確認(rèn)的消息都會確認(rèn),適合批量處理
//?真時場景:每十條消息確認(rèn)一次栗柒,類似
d.Ack(false)
}
}()
log.Printf("?[*]?Waiting?for?messages.?To?exit?press?CTRL+C")
<-forever
}
訂閱模式
訂閱 生產(chǎn)者:
package?main
import?(
"fmt"
"github.com/streadway/amqp"
"log"
"os"
"strings"
"time"
)
/*
廣播模式
發(fā)布方
*/
func?failOnError(err?error,?msg?string)?{
if?err?!=?nil?{
log.Fatalf("%s:?%s",?msg,?err)
panic(fmt.Sprintf("%s:?%s",?msg,?err))
}
}
func?main()?{
conn,?err?:=?amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err,?"Failed?to?connect?to?RabbitMQ")
defer?conn.Close()
ch,?err?:=?conn.Channel()
failOnError(err,?"Failed?to?open?a?channel")
defer?ch.Close()
//?默認(rèn)模式有默認(rèn)交換機礁扮,廣播自己定義一個交換機,交換機可與隊列進行綁定
err?=?ch.ExchangeDeclare(
"logs",???//?name
"fanout",?//?type?廣播模式
true,?????//?durable
false,????//?auto-deleted
false,????//?internal
false,????//?no-wait
nil,??????//?arguments
)
failOnError(err,?"Failed?to?declare?an?exchange")
body?:=?bodyFrom(os.Args)
//?發(fā)布
err?=?ch.Publish(
"logs",?//?exchange?消息發(fā)送到交換機瞬沦,這個時候沒隊列綁定交換機太伊,消息會丟棄
"",?????//?routing?key??廣播模式不需要這個,它會把所有消息路由到綁定的所有隊列
false,??//?mandatory
false,??//?immediate
amqp.Publishing{
ContentType:?"text/plain",
Body:????????[]byte(body),
})
failOnError(err,?"Failed?to?publish?a?message")
log.Printf("?[x]?Sent?%s",?body)
}
func?bodyFrom(args?[]string)?string?{
var?s?string
if?(len(args)?<?2)?||?os.Args[1]?==?""?{
s?=?fmt.Sprintf("%s-%v","hello",?time.Now())
}?else?{
s?=?strings.Join(args[1:],?"?")
}
return?s
}
訂閱 消費者:
package?main
import?(
"fmt"
"github.com/streadway/amqp"
"log"
)
/*
廣播模式
訂閱方
*/
func?failOnError(err?error,?msg?string)?{
if?err?!=?nil?{
log.Fatalf("%s:?%s",?msg,?err)
panic(fmt.Sprintf("%s:?%s",?msg,?err))
}
}
func?main()?{
conn,?err?:=?amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err,?"Failed?to?connect?to?RabbitMQ")
defer?conn.Close()
ch,?err?:=?conn.Channel()
failOnError(err,?"Failed?to?open?a?channel")
defer?ch.Close()
//?同樣要申明交換機
err?=?ch.ExchangeDeclare(
"logs",???//?name
"fanout",?//?type
true,?????//?durable
false,????//?auto-deleted
false,????//?internal
false,????//?no-wait
nil,??????//?arguments
)
failOnError(err,?"Failed?to?declare?an?exchange")
//?新建隊列逛钻,這個隊列沒名字僚焦,隨機生成一個名字
q,?err?:=?ch.QueueDeclare(
"",????//?name
false,?//?durable
false,?//?delete?when?usused
true,??//?exclusive??表示連接一斷開,這個隊列自動刪除
false,?//?no-wait
nil,???//?arguments
)
failOnError(err,?"Failed?to?declare?a?queue")
//?隊列和交換機綁定曙痘,即是隊列訂閱了發(fā)到這個交換機的消息
err?=?ch.QueueBind(
q.Name,?//?queue?name??隊列的名字
"",?????//?routing?key??廣播模式不需要這個
"logs",?//?exchange??交換機名字
false,
nil)
failOnError(err,?"Failed?to?bind?a?queue")
//?開始消費消息芳悲,可開多個訂閱方,因為隊列是臨時生成的边坤,所有每個訂閱方都能收到同樣的消息
msgs,?err?:=?ch.Consume(
q.Name,?//?queue??隊列名字
"",?????//?consumer
true,???//?auto-ack??自動確認(rèn)
false,??//?exclusive
false,??//?no-local
false,??//?no-wait
nil,????//?args
)
failOnError(err,?"Failed?to?register?a?consumer")
forever?:=?make(chan?bool)
go?func()?{
for?d?:=?range?msgs?{
log.Printf("?[x]?%s",?d.Body)
}
}()
log.Printf("?[*]?Waiting?for?logs.?To?exit?press?CTRL+C")
<-forever
}
RPC模式
RPC 應(yīng)答方:
package?main
import?(
"fmt"
"log"
"strconv"
"github.com/streadway/amqp"
)
/*
RPC模式
應(yīng)答方
*/
func?failOnError(err?error,?msg?string)?{
if?err?!=?nil?{
log.Fatalf("%s:?%s",?msg,?err)
panic(fmt.Sprintf("%s:?%s",?msg,?err))
}
}
func?fib(n?int)?int?{
if?n?==?0?{
return?0
}?else?if?n?==?1?{
return?1
}?else?{
return?fib(n-1)?+?fib(n-2)
}
}
func?main()?{
conn,?err?:=?amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err,?"Failed?to?connect?to?RabbitMQ")
defer?conn.Close()
ch,?err?:=?conn.Channel()
failOnError(err,?"Failed?to?open?a?channel")
defer?ch.Close()
q,?err?:=?ch.QueueDeclare(
"rpc_queue",?//?name
false,???????//?durable
false,???????//?delete?when?usused
false,???????//?exclusive
false,???????//?no-wait
nil,?????????//?arguments
)
failOnError(err,?"Failed?to?declare?a?queue")
//?公平分發(fā)?沒有這個則round-robbin
err?=?ch.Qos(
1,?????//?prefetch?count
0,?????//?prefetch?size
false,?//?global
)
failOnError(err,?"Failed?to?set?QoS")
//?消費名扛,等待請求
msgs,?err?:=?ch.Consume(
q.Name,?//?queue
"",?????//?consumer
false,??//?auto-ack
false,??//?exclusive
false,??//?no-local
false,??//?no-wait
nil,????//?args
)
failOnError(err,?"Failed?to?register?a?consumer")
forever?:=?make(chan?bool)
go?func()?{
//請求來了
for?d?:=?range?msgs?{
n,?err?:=?strconv.Atoi(string(d.Body))
failOnError(err,?"Failed?to?convert?body?to?integer")
log.Printf("?[.]?fib(%d)",?n)
//?計算
response?:=?fib(n)
//?回答
err?=?ch.Publish(
"",????????//?exchange
d.ReplyTo,?//?routing?key
false,?????//?mandatory
false,?????//?immediate
amqp.Publishing{
ContentType:???"text/plain",
CorrelationId:?d.CorrelationId,??//序列號
Body:??????????[]byte(strconv.Itoa(response)),
})
failOnError(err,?"Failed?to?publish?a?message")
//?確認(rèn)回答完畢
d.Ack(false)
}
}()
log.Printf("?[*]?Awaiting?RPC?requests")
<-forever
}
RPC 請求方:
package?main
import?(
"fmt"
"log"
"math/rand"
"os"
"strconv"
"strings"
"time"
"github.com/streadway/amqp"
)
/*
RPC模式
請求方
*/
func?failOnError(err?error,?msg?string)?{
if?err?!=?nil?{
log.Fatalf("%s:?%s",?msg,?err)
panic(fmt.Sprintf("%s:?%s",?msg,?err))
}
}
func?randomString(l?int)?string?{
bytes?:=?make([]byte,?l)
for?i?:=?0;?i?<?l;?i++?{
bytes[i]?=?byte(randInt(65,?90))
}
return?string(bytes)
}
func?randInt(min?int,?max?int)?int?{
return?min?+?rand.Intn(max-min)
}
func?fibonacciRPC(n?int)?(res?int,?err?error)?{
conn,?err?:=?amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err,?"Failed?to?connect?to?RabbitMQ")
defer?conn.Close()
ch,?err?:=?conn.Channel()
failOnError(err,?"Failed?to?open?a?channel")
defer?ch.Close()
//?隊列聲明
q,?err?:=?ch.QueueDeclare(
"",????//?name
false,?//?durable
false,?//?delete?when?usused
true,??//?exclusive?為真即連接斷開就刪除
false,?//?noWait
nil,???//?arguments
)
failOnError(err,?"Failed?to?declare?a?queue")
msgs,?err?:=?ch.Consume(
q.Name,?//?queue
"",?????//?consumer
true,???//?auto-ack
false,??//?exclusive???這個為真,服務(wù)器會認(rèn)為這是該隊列唯一的消費者
false,??//?no-local
false,??//?no-wait
nil,????//?args
)
failOnError(err,?"Failed?to?register?a?consumer")
corrId?:=?randomString(32)
err?=?ch.Publish(
"",??????????//?exchange
"rpc_queue",?//?routing?key
false,???????//?mandatory
false,???????//?immediate
amqp.Publishing{
ContentType:???"text/plain",
CorrelationId:?corrId,
ReplyTo:???????q.Name,
Body:??????????[]byte(strconv.Itoa(n)),
})
failOnError(err,?"Failed?to?publish?a?message")
for?d?:=?range?msgs?{
if?corrId?==?d.CorrelationId?{
res,?err?=?strconv.Atoi(string(d.Body))
failOnError(err,?"Failed?to?convert?body?to?integer")
break
}
}
return
}
func?main()?{
rand.Seed(time.Now().UTC().UnixNano())
n?:=?bodyFrom(os.Args)
log.Printf("?[x]?Requesting?fib(%d)",?n)
res,?err?:=?fibonacciRPC(n)
failOnError(err,?"Failed?to?handle?RPC?request")
log.Printf("?[.]?Got?%d",?res)
}
func?bodyFrom(args?[]string)?int?{
var?s?string
if?(len(args)?<?2)?||?os.Args[1]?==?""?{
s?=?"30"
}?else?{
s?=?strings.Join(args[1:],?"?")
}
n,?err?:=?strconv.Atoi(s)
failOnError(err,?"Failed?to?convert?arg?to?integer")
return?n
}
本文來自php中文網(wǎng)的golang欄目:https://www.php.cn/be/go/