heimeil

第 1925 号会员 /

回复了 ioioj5 创建的主题: channel必须显示的使用close()方法关闭么?

由于for range的特性必须要等到close之后才会结束,如果不想通过close结束,可以通过外部条件控制for循环结束,比如再用一个chan通知结束,或者从chan传过来一个特定的值来判断结束循环,所有使用完之后不再有地方引用的chan会自动被垃圾回收。

回复了 Flower_550838476 创建的主题: golang des解密有人会吗?

是DES算法的key就只有8byte(56bit参与运算+8bit校验位),你这个Java实现给的key是有问题的。

https://docs.oracle.com/javase/7/docs/api/javax/crypto/spec/DESKeySpec.html#DESKeySpec(byte[])

Creates a DESKeySpec object using the first 8 bytes in key as the key material for the DES key.

文档说了只用前8个字节,更长的key就没意义了,所以go里的实现就只用des.NewCipher([]byte("Z*$Mcs8C"))就行了

回复了 snake117 创建的主题: n++ 和 n= n+1、n+=1 不一样?

我用go1.9.2 windows/amd64简单跑了一下你的代码,多跑几次发现有几率会出现空指针异常,可以肯定你的实现是有问题的,debug断点定位到main的for循环里的p.Key(),p为nil,没时间帮你看细节,你还是自己梳理一下逻辑吧,问题应该不是在n怎么+1上面。

回复了 snake117 创建的主题: n++ 和 n= n+1、n+=1 不一样?

我在docker里用1.10试了一下,没问题。

这个不应该会有问题,再仔细debug一下吧,这要是真的有问题就非常致命了,排查出来真的有问题就及早向官方提issue

回复了 gao88 创建的主题: io.ReadFull接收不到数据

func ReadFull(r Reader, buf []byte) (n int, err error)

ReadFull读取会有两种返回情况:

  1. 读满了buf
  2. 读到EOF

你要debug这几种情况:

  1. buf是否在其他地方被修改,导致无法读满buf
  2. 客户端是否正确的发送了数据

另外能收到EOF,说明连接是通的。

回复了 Szzzl 创建的主题: 刚刚开始学Golang,请问这个是什么意思?

二进制操作,大多数语言差不多都是类似的操作。将1左移100位,这个数就非常大了,都已经超过了常用整形中最大的Int64了,得要13个字节才能装得下,不能指派类型,但能做比较使用,这个取名Big应该就是要这么用的。

回复了 aaaaaaaa 创建的主题: context包 WithValue(ctx, key ,val) 的key参数应该是非导出的内置类型, 如何理解?

官方文档没有特别描述GC啊,我看见的是使用非内置类型是为了避免和其他包冲突,直接看源码:

// WithValue returns a copy of parent in which the value associated with key is
// val.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
//
// The provided key must be comparable and should not be of type
// string or any other built-in type to avoid collisions between
// packages using context. Users of WithValue should define their own
// types for keys. To avoid allocating when assigning to an
// interface{}, context keys often have concrete type
// struct{}. Alternatively, exported context key variables' static
// type should be a pointer or interface.
func WithValue(parent Context, key, val interface{}) Context {
    if key == nil {
        panic("nil key")
    }
    if !reflect.TypeOf(key).Comparable() {
        panic("key is not comparable")
    }
    return &valueCtx{parent, key, val}
}

// A valueCtx carries a key-value pair. It implements Value for that key and
// delegates all other calls to the embedded Context.
type valueCtx struct {
    Context
    key, val interface{}
}

func (c *valueCtx) String() string {
    return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
}

func (c *valueCtx) Value(key interface{}) interface{} {
    if c.key == key {
        return c.val
    }
    return c.Context.Value(key)
}

关键在L39,当前ctx没有还会去父ctx获取,和JS原型链调用类似,如果在不知情的情况下用了和父ctx相同的key并且是内置类型就可能会有异常情况,文档说用自定义类型来避免这种情况是用了interface的特性,看下面例子:

package main

import (
    "fmt"
)

func main() {
    type myInt int
    i := myInt(1)
    fmt.Println(1 == i)     // true
    fmt.Println(compare(i)) // false
    fmt.Println(compare(1)) // true
}

func compare(key interface{}) bool {
    return 1 == key
}

interface的比较不只比较值还比较类型,这就是文档说的用非内置类型来避免冲突。

回复了 cumt_21g 创建的主题: 妈蛋,整个go社区就没有一个正常的日志库?

package main

import (
    "fmt"
    "io"
    "log"
    "os"
)

type writer struct {
    io.Writer
}

// 3
func (w *writer) Write(p []byte) (n int, err error) {
    fmt.Println(string(p))
    return w.Writer.Write(p)
}

func main() {
    logFile, err := os.Create("hello.log")
    if err != nil {
        panic(err)
    }
    defer logFile.Close()

    // 1
    w := io.MultiWriter(os.Stdout, logFile)

    // 4 2
    logger := log.New(&writer{Writer: w}, "| GOGOGO | ", log.Llongfile)

    logger.Println("Hello World!")
}

1、2用标准库的log直接能满足,3、4可能还是要看具体需求,但自己实现这种功能的log还是不难的。

回复了 haha03942008 创建的主题: 怎么样通过pid得到进程的stderrpipe,求代码,谢谢大家了!

三种情况:
1)这个进程如果能由你启动的话,直接在你的程序里用https://golang.org/pkg/os/exec/#Command来执行就直接能拿到全部标准流,或者用命令行参数重定向stderr到文件./cmd 2>/path/to/file,再读文件就行了;

2)如果是基础功能(系统组件或数据库之类),你不好去控制进程启动的话,这类标准组件都能配置日志输出到指定文件,配置后读文件就行了;

3)如果不允许你碰这个进程,只能通过pid去获取的话就比较麻烦,涉及Linux底层,拿不拿的到也还要看几种情况。

回复了 bigbear 创建的主题: 如何不复制HTTP.request.body 的字节流,实现切面日志?

这个切片避免不了copy了,数据流不能直接使用,你说的这个方案应该是比较合适的解决方案了,在数据流正常读取流程之前切片肯定要全部读完才能使用,再又在内存里模拟成数据流供正常流程读取,这个切片的位置只能这样操作。

如果非要zerocopy的话,可以换一个切片点,在数据读取完后,一般都需要其他处理,比如解析JSON,可以将解析JSON封装成一个方法,再在这个方法内完成切片就行,直接使用已经读取完全的数据。