Почему не определено: выдается ошибка при передаче пользовательской структуры как указателей? - PullRequest
0 голосов
/ 11 января 2020
package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    type CustomInfo struct {
        Name string
        Size int
    }

    type Error struct {
        ErrorCode int
        ErrorMsg  string
    }
    type Product struct {
        Fruit string
        CInfo CustomInfo
        Err   Error
    }

    var pr1 = Product{
        Fruit: "Orange",
        CInfo: CustomInfo{
            Name: "orango botanica",
            Size: 3,
        },
        Err: Error{
            ErrorMsg:  "",
        },
    }

    var pr2 = Product{
        Fruit: "Apple",
        CInfo: CustomInfo{
            Name: "appleo botanica",
            Size: 4,
        },
        Err: Error{
            ErrorMsg:  "",
        },
    }

    var products []Product
    products = append(products, pr1, pr2)
    mrshl, _ := json.Marshal(products)

    var productsRes []Product
    err := json.Unmarshal([]byte(mrshl), &productsRes)
    if err != nil {
        fmt.Println(err)
    }
    //fmt.Println(productsRes[0].Fruit)
    //fmt.Println(productsRes[1])
    //fmt.Println(unmrshl)
    validate(&productsRes)
}

func validate(bRes *Product){
    fmt.Println(bRes[0].Fruit)
    fmt.Println(bRes[1])
}

Почему я получаю ./prog.go:61:22: undefined: Product?

Ответы [ 2 ]

1 голос
/ 11 января 2020

Я немного изменил пример обновленной игровой площадки здесь .

Вы не хотите указатель на слайса, вы просто хотите передать сам слайс , Передавать указатель по своей сути не неправильно, здесь просто нет необходимости. Срез означает: «Я (main) даю вам (validate) доступ к массиву, который я создал». Заголовок слайса предоставляет пользователю user-of-slice:

  • доступ к массиву (посредством индексации: bRes[i] является i -ым элементом массива);
  • длина массива: len(bRes) - циклы for используют это неявно; и
  • емкость массива (в данном примере не используется).

Записав в bRes[i], мы можем обновить любое или все поля одного из Product s в базовом массиве. Это то, что делает второй l oop, который я добавил к validate.

Примечание: строки 47-48, которые читают:

var products []Product
products = append(products, pr1, pr2)

использует append немного странно: поскольку у нас есть только два продукта, мы можем построить срез непосредственно с помощью:

products := []Product{pr1, pr2}

Значение products будет изначально nil. Заголовок нулевого среза фактически говорит о том, что длина и емкость равны нулю, и, в конце концов, базовый массив отсутствует. При добавлении к срезу nil всегда append выделяет новый базовый массив. Функция append возвращает новый фрагмент, который использует новый массив. 1 Так что при настройке этого нулевого среза требуется немало усилий, только чтобы его выбросить. Опять же, это не неправильно , это просто не нужно.

(Между тем, вы получаете +1 балл за проверку на ошибку с json.Unmarshal, но -1 балл, или, может быть, минус половина точка, для не проверка на ошибку от json.Marshal. ?)


1 append всегда создает новый заголовок среза В некоторых случаях новый заголовок может повторно использовать старый массив. или он может использовать новый массив. Операция append будет повторно использовать старый, уже существующий массив тогда и только тогда, когда добавленные элементы вписываются в существующий массив на основе емкости, указанной в исходном заголовке слайса. Поскольку заголовок nil имеет нулевую емкость, его существующий массив не может быть использован здесь.

1 голос
/ 11 января 2020

Ваше определение структуры находится в main и, следовательно, выходит за рамки validate, оно может использоваться только внутри вашей основной функции. Он должен работать, когда вы перемещаете определения структуры из main

Кроме того, ваша validate функция, вероятно, должна принимать []Product (фрагмент Product), а не *Product (указатель на одноместный Product)

...