package main
import "fmt"
func main() {
fmt.Println("main start")
a()
fmt.Println("main end")
}
func a() {
fmt.Println("a start")
defer func() {
fmt.Println("c")
if err := recover(); err != nil {
fmt.Println(err) //这里的err其实就是panic传入的内容,55
}
fmt.Println("d")
}()
f()
fmt.Println("a end")
}
func f() {
fmt.Println("f start")
panic(55)
fmt.Println("f end")
}
输出:
main start
a start
f start
c
55
d
main end
package main
import (
"fmt"
)
func main() {
A()
B()
C()
}
func A() {
fmt.Println("Func A")
}
func B() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Recover in B")
}
}()
panic("Panic in B")
}
func C() {
fmt.Println("Func C")
}
输出:
Func A
Recover in B
Func C
一、在函数体执行结束后按照调用顺序的相反顺序逐个执行。
二、即使函数发生严重错误也会执行。
三、支持匿名函数的调用。
四、通常用于资源清理、文件关闭、解锁以及记录时间等操作。
五、通过与匿名函数配合可在 return 之后修改函数的计算结果。
六、如果函数体内某个变量作为 defer 时匿名函数的参数,则在定义 defer 时即已经获得了拷贝,否则则是引用某个变量的地址。
七、panic 可以在任何地方引发,但 recover 只有在 defer 调用的函数中有效。
八、个人测试,ctrl-C 和 killall 的时候,defer 没有被执行。
package main
import "fmt"
func main() {
fmt.Println("f1() = ", f1())
fmt.Println("f2() = ", f2())
//输出
//f1() = 1
//f2() = 0
}
func f1() (result int) {
defer func() {
result++
}()
return 0
}
func f2() (result int) {
return 0
defer func() {
result++
}()
return 0
}
package main
import (
"log"
)
func main() {
defer log.Println("11111111")
defer log.Println("22222222")
defer log.Println("33333333")
}
/*
输出:
2018/02/27 09:01:21 33333333
2018/02/27 09:01:21 22222222
2018/02/27 09:01:21 11111111
*/
package main
import (
"log"
)
func main() {
defer log.Println("11111111")
defer log.Println("22222222")
defer log.Println("33333333")
panic("I panic in here.")
}
/*
输出:
2018/02/27 09:01:21 33333333
2018/02/27 09:01:21 22222222
2018/02/27 09:01:21 11111111
panic: I panic in here.
goroutine 1 [running]:
main.main()
e:/Go/GOPATH/src/jian/test/test.go:11 +0x172
exit status 2
*/
package main
import (
"log"
)
func main() {
defer log.Println("11111111")
f1()
defer log.Println("55555555")
}
func f1() {
defer log.Println("22222222")
defer log.Println("33333333")
panic("I panic in here.")
defer log.Println("44444444") //unreachable code.
}
/*
输出:
$ go run test.go
2018/02/27 09:09:46 33333333
2018/02/27 09:09:46 22222222
2018/02/27 09:09:46 11111111
panic: I panic in here.
goroutine 1 [running]:
main.f1()
e:/Go/GOPATH/src/jian/test/test.go:16 +0x10c
main.main()
e:/Go/GOPATH/src/jian/test/test.go:9 +0x93
exit status 2
*/
package main
import (
"fmt"
)
func main() {
for i := 0; i < 3; i++ {
defer func(i int) {
fmt.Println(i)
}(i)
}
}
/*
输出:
2
1
0
*/
package main
import (
"fmt"
)
func main() {
for i := 0; i < 3; i++ {
defer func() {
fmt.Println(i)
}()
}
}
/*
输出:
3
3
3
*/
因为 i 没有作为参数传递进去,所以每个闭包函数都是引用同一个 i 变量。
package main
func main() {
test()
}
func test() {
println("test start")
defer println("test end")
for i := 0; i < 5; i++ {
println("i =", i)
defer println("defer i =", i)
}
println("end of loop")
}
/*
输出:
test start
i = 0
i = 1
i = 2
i = 3
i = 4
end of loop
defer i = 4
defer i = 3
defer i = 2
defer i = 1
defer i = 0
test end
*/
这个输出说明了在循环体中的 defer 一样要等到函数结束了才会被执行,如果这个 defer 后面是关闭文件的话,那就会有大量的文件描述符被占用,这个时候就不能使用 defer。
看下是否完全弄懂 defer
package main
import "fmt"
func main() {
var fs = [4]func(){}
for i := 0; i < 4; i++ {
defer fmt.Println("defer i = ", i)
defer func() {
fmt.Println("defer_closure i = ", i)
}()
fs[i] = func() {
fmt.Println("closure i = ", i)
}
}
for _, f := range fs {
f()
}
}
输出:
closure i = 4
closure i = 4
closure i = 4
closure i = 4
defer_closure i = 4
defer i = 3
defer_closure i = 4
defer i = 2
defer_closure i = 4
defer i = 1
defer_closure i = 4
defer i = 0
redis-server.exe redis.windows.conf
默认为127.0.0.1:6379
redis-cli -h host -p port -a password
redis-cli.exe -h 127.0.0.1 -p 6379
可简写为redis-cli
config get * : 获取所有的信息
config get requirepass : 获取密码
config get dir : 获取redis的目录
config get requirepass
设置密码: config set requirepass “123456”
auth “123456”
取消密码: config set requirepass “”
save : 该命名将在redis目录下创建dump.rdb文件。
bgsave: 该命令将在后台执行。
如果需要恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 安装目录并重新启动服务即可。
添加,查看
127.0.0.1:6379> hset runoobkey name "huangjian"
(integer) 0
127.0.0.1:6379> hget runoobkey name
"huangjian"
同时添加多个
127.0.0.1:6379> hmset runoobkey name "jian" age "123"
OK
127.0.0.1:6379> hgetall runoobkey
1) "name"
2) "jian"
3) "age"
4) "123"
127.0.0.1:6379> hget runoobkey name
"jian"
127.0.0.1:6379> hget runoobkey age
"123"
删除
127.0.0.1:6379> hdel runoobkey age
(integer) 1
127.0.0.1:6379> hgetall runoobkey
1) "name"
2) "huangjian"
127.0.0.1:6379> hdel runoobkey age
(integer) 0
判断键是否存在
127.0.0.1:6379> hexists runoobkey age
(integer) 0
127.0.0.1:6379> hexists runoobkey name
(integer) 1
在客户端1订阅: subscribe mychannel
在客户端2发布消息: publish mychannel “Redis is great”
然后客户端1就可以收到。
redis-cli keys ‘*’
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"os"
)
func main() {
genRsaKey(1024)
}
func genRsaKey(bits int) error {
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return err
}
derStream := x509.MarshalPKCS1PrivateKey(privateKey)
block := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: derStream,
}
file, err := os.Create("private.pem")
if err != nil {
return err
}
err = pem.Encode(file, block)
if err != nil {
return err
}
publicKey := &privateKey.PublicKey
derPkix, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return err
}
block = &pem.Block{
Type: "PUBLIC KEY",
Bytes: derPkix,
}
file, err = os.Create("public.pem")
if err != nil {
return err
}
err = pem.Encode(file, block)
if err != nil {
return err
}
return nil
}
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
)
var (
publicKey []byte
privateKey []byte
)
func init() {
pub, _ := ioutil.ReadFile("../genRSAKey/public.pem")
publicKey = []byte(pub)
pri, _ := ioutil.ReadFile("../genRSAKey/private.pem")
privateKey = []byte(pri)
}
func RsaEncrypt(origData []byte) ([]byte, error) {
block, _ := pem.Decode(publicKey)
if block == nil {
return nil, errors.New("public key error")
}
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
pub := pubInterface.(*rsa.PublicKey)
return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
}
func RsaDecrypt(ciphertext []byte) ([]byte, error) {
block, _ := pem.Decode(privateKey)
if block == nil {
return nil, errors.New("Private key error!")
}
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
}
func main() {
data, err := RsaEncrypt([]byte("1342042894@qq.com"))
if err != nil {
panic(err)
}
fmt.Println(string(data))
origData, err := RsaDecrypt(data)
if err != nil {
panic(err)
}
fmt.Println(string(origData))
}
package main
import (
"fmt"
"time"
"github.com/garyburd/redigo/redis"
)
func newPool(addr string) *redis.Pool {
return &redis.Pool{
MaxIdle: 3,
IdleTimeout: 240 * time.Second,
Dial: func() (redis.Conn, error) { return redis.Dial("tcp", addr) },
}
}
func main() {
testBasic()
testHash()
testPubSub()
}
func testPubSub() {
pool := newPool("127.0.0.1:6379")
psc := redis.PubSubConn{Conn: pool.Get()}
psc.Subscribe("mychannel")
for {
switch v := psc.Receive().(type) {
case redis.Message:
fmt.Println("redis.Message", v.Channel, v.Data)
case redis.Subscription:
fmt.Println("redis.Subscription")
case redis.PMessage:
fmt.Println("redis.PMessage")
case error:
fmt.Println("find an error")
}
}
}
func testHash() {
pool := newPool("127.0.0.1:6379")
conn := pool.Get()
defer conn.Close()
testHGET(conn)
testHSET(conn)
testHGET(conn)
testHDEL(conn)
testHGET(conn)
}
func testHSET(conn redis.Conn) {
conn.Do("HSET", "user1024", "roomID", 123)
}
func testHGET(conn redis.Conn) {
buf, err := redis.String(conn.Do("HGET", "user1024", "roomID"))
if err != nil && err != redis.ErrNil {
fmt.Println("Get user room err:", err)
return
}
fmt.Println("buf:", buf)
}
func testHDEL(conn redis.Conn) {
conn.Do("HDEL", "user1024", "roomID")
}
func testBasic() {
pool := newPool("127.0.0.1:6379")
conn := pool.Get()
defer conn.Close()
conn.Do("SET", "hello", "world")
s, _ := redis.String(conn.Do("GET", "hello"))
fmt.Printf("%#v\n", s)
}
package main
import (
"fmt"
"math/rand"
"os"
"time"
)
type GameContext struct {
SecretNumber int
Retries int
Won bool
Next GameState
}
type GameState interface {
executeState(*GameContext) bool
}
type StartState struct{}
func (s *StartState) executeState(c *GameContext) bool {
c.Next = &AskState{}
rand.Seed(time.Now().UnixNano())
c.SecretNumber = rand.Intn(10)
fmt.Println("Introduce a number of retries to set the difficulty:")
fmt.Fscanf(os.Stdin, "%d\n", &c.Retries)
return true
}
type AskState struct{}
func (a *AskState) executeState(c *GameContext) bool {
fmt.Printf("Introduce a number between 0 and 10, you have %d tries left\n", c.Retries)
var n int
fmt.Fscanf(os.Stdin, "%d\n", &n)
c.Retries = c.Retries - 1
if n == c.SecretNumber {
c.Won = true
c.Next = &FinishState{}
}
if c.Retries == 0 {
c.Next = &FinishState{}
}
return true
}
type FinishState struct{}
func (f *FinishState) executeState(c *GameContext) bool {
if c.Won {
c.Next = &WinState{}
} else {
c.Next = &LoseState{}
}
return true
}
type WinState struct{}
func (w *WinState) executeState(c *GameContext) bool {
println("Congrats, you won")
return false
}
type LoseState struct{}
func (l *LoseState) executeState(c *GameContext) bool {
fmt.Printf("You lose, the corrent number is: %d\n", c.SecretNumber)
return false
}
func main() {
start := StartState{}
game := GameContext{
Next: &start,
}
for game.Next.executeState(&game) {
}
}