передача функции int [], но функция возвращает пустой массив - PullRequest
0 голосов
/ 12 марта 2019

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

employeeDataInt - массив целых чисел, а employeeDataString - массив строк.

Я прошу прощения, если это глупый вопрос, но я новичок. Спасибо

package main

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

func strToInt(employeeDataString []string, emplyoeeDataInt []int) []int {
    for _, i := range employeeDataString[2:] {
        j, err := strconv.Atoi(i)
        if err != nil {
            panic(err)
        }
        employeeDataInt = append(employeeDataInt, j)
        fmt.Println(employeeDataInt) //this prints out the appropriate array

    }
    return employeeDataInt
}

func main() {
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Enter file name: ")
    fileName, err := reader.ReadString('\n')
    if err != nil {
        log.Fatalf("failed opening file: %s", err)
    }
    fileName = strings.TrimSuffix(fileName, "\n")

    file, err := os.Open(fileName)
    scanner := bufio.NewScanner(file)
    scanner.Split(bufio.ScanLines)
    var employeeLine []string

    for scanner.Scan() {
        employeeLine = append(employeeLine, scanner.Text())
    }

    file.Close()
    var employeeDataString = []int{}
    for _, employee := range employeeLine {
        employeeDataString := strings.Split(employee, " ")

        strToInt(employeeDataString, employeeDataInt)
        fmt.Println(playerData2) //this is outputting just `[]`

    }
}

Ответы [ 2 ]

2 голосов
/ 12 марта 2019

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

strToInt(employeeDataString, employeeDataInt)
// should be
employeeDataInt = strToInt(employeeDataString, employeeDataInt)

И при этом вы никогда не назначаете playerData2.Так что fmt.Println(playerData2) всегда будет [].

Но кроме этого, здесь есть некоторые тонкие проблемы с использованием массивов / кусочков:

Во-первых, разница между Slices и Arrays:

Go не позволяет напрямую работать с массивами.Если они не имеют фиксированной длины ([3]int{} или []int{1,2,3]), вы на самом деле смотрите не на массив, а на Slice ([]int).

Срез - это просто указатель на массив (вместе с его емкостью и некоторой другой информацией), и он, по сути, позволяет Go безопасно работать с массивами, потому что вы никогда не увеличиваете существующий массив (размер массива равенисправлено при инициализации).Таким образом, вы никогда не можете добавить в массив.

То, что Go делает, чтобы создать иллюзию добавления массива, заключается в том, что базовый массив больше, чем требуется, и Slice контролирует доступ к этому массиву.Таким образом, если базовый массив имеет емкость 5 и вы уже сохранили в нем 3 элемента, вы можете выполнять 2 append операций без необходимости выделять новый массив и копировать существующие элементы массива в новую ячейку памяти.

Таким образом, когда вы передаете []int, вы фактически передаете указатель массива (по значению).

Это приводит к следующему уловке в вашем коде: использование append.Как упоминалось выше, append берет Slice, просматривает базовый массив и сколько фактически осталось места, а затем добавляет к нему или выделяет новый массив.Если выделен новый массив, append возвращает новый срез, который указывает на новый массив.

Так что вызов:

foo := []{1,2,3}
append(foo, 4)
append(foo, 5)
append(foo, 6)
fmt.Print(foo) 
// => might return 1,2,3,4,5

Вы всегда должны взятьвозвращаемое значение append в противном случае вы рискуете по-прежнему ссылаться на «старый» фрагмент, к которому не добавлены новые элементы.

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

0 голосов
/ 12 марта 2019

В вашем коде есть несколько проблем:

  • Вы отбрасываете возвращаемое значение strToInt.
  • Вы пытаетесь использовать employeeDataInt in main но он там не определен (что должно вызывать ошибку компиляции, а не проблему времени выполнения).
  • Вы объявляете employeeDataString дважды, в двух разных областях действия в main (внутри и снаружиfor loop), с двумя различными типами ([]string и []int).Переменная внешней области не используется, поэтому также должна вызывать ошибку компиляции.
  • Вы печатаете playerData2, который никогда не определяется или не используется - опять же, это должно вызывать ошибку компилятора, а не некорректное поведение.

Учитывая, что в коде были ошибки компиляции, либо в вашем сообщении отсутствовал какой-то важный код, либо вы не заметили / не упомянули ошибки компиляции.

Правильный код внутриОсновным будет:

var employeeDataInt []int  // Seems like you just have the wrong variable name here
for _, employee := range employeeLine {
    employeeDataString := strings.Split(employee, " ")

    // You're missing the assignment here
    employeeDataInt = strToInt(employeeDataString, employeeDataInt)
    fmt.Println(employeeDataInt) // This was referencing the wrong variable

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...