Добавление фрагмента с пользовательским вводом с функциями - PullRequest
0 голосов
/ 07 октября 2019

При запуске этого кода данные среза не заменяются пользовательским вводом. Но при удалении комментариев и обычном запуске кода без функций данные в слайсе заменяются.

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    vriendinnen := []string{"vriendin1", "vriendin2", "vriendin3"}
    koken(vriendinnen[0])
    koken(vriendinnen[1])
    koken(vriendinnen[2])

}

func koken(vriendinnen string) {
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Wat Zijn de namen van de vriendinnen: ")
    vriendinnen, _ = reader.ReadString('\n')
    // vriendinnen[1], _ = reader.ReadString('\n')
    // vriendinnen[2], _ = reader.ReadString('\n') 
}

Это работает


    vriendinnen := []string{"vriendin1", "vriendin2", "vriendin3"}
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Wat Zijn de namen van de vriendinnen: ")
    vriendinnen[0], _ = reader.ReadString('\n')
    vriendinnen[1], _ = reader.ReadString('\n')
    vriendinnen[2], _ = reader.ReadString('\n')
    fmt.Println(vriendinnen)

Ответы [ 2 ]

1 голос
/ 07 октября 2019

1 / Go передает все по значению.

https://golang.org/ref/spec#Calls

При вызове функции значение и аргументы функции оцениваются в обычном порядке. После того, как они оценены, параметры вызова передаются по значению функции, и вызываемая функция начинает выполнение

Таким образом, чтобы записать значение каждой строковой записи срезов, вы можете использоватьуказатели. В этом примере указатель на значение создается и передается функции. Функция обновляет значение, хранящееся по адресу указателей.

Функция небезопасна для нулевых указателей.

package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
)

func main() {
    vriendinnen := []string{"vriendin1", "vriendin2", "vriendin3"}
    koken(&vriendinnen[0])
    koken(&vriendinnen[1])
    koken(&vriendinnen[2])

    log.Println(vriendinnen)
}

func koken(vriendinnen *string) {
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Wat Zijn de namen van de vriendinnen: ")
    *vriendinnen, _ = reader.ReadString('\n')
    // vriendinnen[1], _ = reader.ReadString('\n')
    // vriendinnen[2], _ = reader.ReadString('\n')
    // reader.WriteTo(w)
}

2 / Bufio.Reader буферизуется, поэтому неправильное управление может привести к потере данных.

эта версия программы печатает некоторые подробности

package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
)

func main() {
    vriendinnen := []string{"vriendin1", "vriendin2", "vriendin3"}
    koken(&vriendinnen[0])
    koken(&vriendinnen[1])
    koken(&vriendinnen[2])
    log.Println(vriendinnen)
}

func koken(vriendinnen *string) {
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Wat Zijn de namen van de vriendinnen: ")
    *vriendinnen, _ = reader.ReadString('\n')
    fmt.Println()
    log.Println(reader.Buffered())
    reader.WriteTo(os.Stdout)
}

Запустите ее с echo -e "1\n2\n3" | go run main.go, она выдаст

Wat Zijn de namen van de vriendinnen: 
2019/10/07 13:36:53 4
2
3
Wat Zijn de namen van de vriendinnen: 
2019/10/07 13:36:53 0
Wat Zijn de namen van de vriendinnen: 
2019/10/07 13:36:53 0
2019/10/07 13:36:53 [1
  ]

В первой строке чтения экземпляр bufio.Reader имеет еще 4непрочитанные байты во внутренний буфер (https://golang.org/src/bufio/bufio.go#L32).

4 байта "2\n3"+"\n" (echo добавляет конечный NL).

Эти четыре байта были считаны со стандартного ввода и сохраненыв bufio.Reader. Этот буферизованный считыватель и его состояние теряются при выходе из функции.

В следующей строке чтения он выводит 0 непрочитанных байтов, фактически он достиг io.EOF при os.Stdin и больше нечего читать.

Чтобы это исправить, настройте свой код для повторного использования bufio.Reader.

Кроме того, необходимо соблюдать осторожность, чтобы правильно обрабатывать ошибки, чтобы правильно обрабатыватьio.EOF.

package main

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

func main() {

    vriendinnen := []string{"vriendin1", "vriendin2", "vriendin3"}
    reader := bufio.NewReader(os.Stdin)
    var err error
    for i := 0; i < len(vriendinnen); i++ {
        fmt.Print("Wat Zijn de namen van de vriendinnen: ")
        vriendinnen[i], err = reader.ReadString('\n')
        if err != nil {
            if err == io.EOF {
                err = nil
            }
            break
        }
    }
    if err != nil {
        log.Fatal(err)
    }
    log.Println(vriendinnen)
}
0 голосов
/ 07 октября 2019

Возможно, причина в том, что передача параметра в Go - это передача значения. Когда вы используете функцию koken, она передает только копию vriendinnen[0](/[1]/[2]). Операция в функции не повлияет на исходное значение среза.
Если вы хотите изменить значение среза, передав весь срез функции koken, тогда будет выполнена операция изменения. Если вы хотите добавить к срезу, метод выше не может закончить эту работу. Тогда вам может понадобиться использовать срез в качестве возвращаемого значения функции и назначить возвращаемое значение исходному срезу. Это связано со структурой слайса в Go.

...