2016-01-11 8 views
2

У меня есть соединение, созданное, как это:Почему conn.Read() ничего не записывает в [] байт, но работает bufio.Reader.ReadString()?

conn, err = net.Dial("tcp", "127.0.0.1:20000") 

Я попытался чтения из этой связи двух способов. Я думаю, они оба должны работать, но первый вариант этого не делает.

Вот первый способ сделать это:

var bytes []byte 
for i := 0; i < 4; i++ { 
    conn.Read(bytes) 
} 
fmt.Printf("%v", bytes) 

Выход этого метода:

[] 

И здесь то же самое, сделано с bufio.Reader:

func readResponse(conn net.Conn) (response string, err error) { 
    reader := bufio.NewReader(conn) 
    _, err = reader.Discard(8) 
    if err != nil { 
     return 
    } 

    response, err = reader.ReadString('\n') 

    return 
} 

Эта функция возвращает ответ, заданный сервером на другом конце TCP-соединения.

Почему bufio.Reader.Read() работает, но net.Conn.Read() нет?

+1

Ну, это совершенно очевидно: 'Read' читает ** в ** предоставленный' [] byte'. Ваш '[] byte' пуст, имеет нулевую длину, и вся эта нулевая длина заполняется. Так что технически ваш 'Read'call работал так, как он полностью заполнял предоставленный байтовый фрагмент данными из соединения. Вы отправились в тур по городу? – Volker

+0

Спасибо. Я новичок во многих концепциях, поэтому некоторые вещи, которые я читал в туре, или первый раз, когда я смотрю на документацию о функции, переходят мне в голову, не осознавая этого.Извините за раздражение. –

ответ

7

Метод Conn.Read() предназначен для реализации io.Reader, общего интерфейса для чтения данных из любого источника байтов в []byte. Цитата из документа Reader.Read():

Чтение считывает до len (p) байт в p.

Так Read() читает до len(p) байт, но так как вы передаете nil кусочек, он не будет ничего (длина nil срез 0) читать. Пожалуйста, прочитайте связанный документ, чтобы узнать, как работает Reader.Read().

Reader.Read() не выделяет буфер ([]byte), где Считанные данные будут сохранены, вы должны создать и передать его, например:

var buf = make([]byte, 100) 
n, err := conn.Read(buf) 
// n is the number of read bytes; don't forget to check err! 

Не забудьте всегда проверять возвращенный error который может быть io.EOF, если конец данных достигнут. Общий договор io.Reader.Read() также позволяет возвращать некоторую ошибку не nil (включая io.EOF) и некоторые прочитанные данные (n > 0) в то же время. Количество прочитанных байтов будет в n, что означает, что полезны только первые n байты buf (другими словами: buf[:n]).

Ваш другой пример с использованием bufio.Reader работает, потому что вы позвонили Reader.ReadString(), который не требует аргумента []byte. Если бы вы использовали метод bufio.Reader.Read(), вам также пришлось бы пройти кусочек не nil, чтобы фактически получить некоторые данные.

+1

Я также хотел бы отметить, что новички часто сбиваются с ложным ожиданием 'Read()', считывая именно столько данных, чтобы заполнить весь фрагмент. «Проблема» находится в этих словах «до» в строке документации, которая фактически означает «любое количество байтов между 1 и длиной входного буфера». Чтобы заполнить весь буфер, следует использовать ['io.ReadFull()'] (https://golang.org/pkg/io/#ReadFull). Это поведение следует за семантикой ['s readall (' s readall) для POSIX (http://pubs.opengroup.org/onlinepubs/009695399/functions/read.html). – kostix