Каков идиоматический метод и стиль объединения двух фрагментов в go?

При объединении двух фрагментов, например. фрукты и овощи, чтобы создать треть, например. еда. казалось бы, имеет смысл добавить фрукты и овощи и приписать результат непосредственно еде.
Проверка golangci-lint: «appendAssign» предполагает, что это неприемлемый способ, альтернатива (см. ниже) предпочтительнее.

Каков наиболее идиоматический способ добиться этого?

Код для иллюстрации вопроса: https://go.dev/play/p/IFV6o92-HTb

package main

import "fmt"

func main() {
    // fails linting with: gocritic: appendAssign: append result not assigned to the same slice
    fruits := []string{"banana", "strawberry"}
    vegetables := []string{"potato", "carrot"}

    food := append(fruits, vegetables...)

    fmt.Println(food)

    // reset
    food = nil

    // passes linting
    food = fruits
    food = append(food, vegetables...)

    fmt.Println(food)
}

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

Peter 29.06.2024 13:30

Обсуждение здесь: github.com/go-critic/go-critic/issues/865 . Я не поклонник предупреждений линтера, которые имеют такие ложные срабатывания.

Paul Hankin 29.06.2024 13:34

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

Paul Hankin 29.06.2024 13:36
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
2
3
84
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Одной из причин может быть то, что вы можете получить удивительные результаты, например (Go Playground):

func main() {
    fruits := []string{"banana", "strawberry", "apple", "cherry"}
    vegetables := []string{"potato", "carrot"}

    food := append(fruits[:2], vegetables...)

    fmt.Println(food) // [banana strawberry potato carrot]
    fmt.Println(fruits) // [banana strawberry potato carrot]
}

или даже

func main() {
    allFruits := []string{"banana", "strawberry", "apple", "cherry"}
    fruits := allFruits[:2]
    vegetables := []string{"potato", "carrot"}

    food := append(fruits, vegetables...)

    fmt.Println(food) // [banana strawberry potato carrot]
    fmt.Println(allFruits) // [banana strawberry potato carrot]
}

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

Лучше всего использовать срезы.Конкат:

    food := slices.Concat(fruits, vegetables)

альтернативой будет:

    food := make([]string, 0, len(fruits)+len(vegetables))
    food = append(food, fruits...)
    food = append(food, vegetables...)

имея преимущество предварительно выделенного массива. Также возможно:

    var food []string
    food = append(food, fruits...)
    food = append(food, vegetables...)

Хотя то, что вы делаете, нормально с точки зрения языка, это может удивить людей, быстро читающих ваш код.

Вы можете не согласиться и игнорировать предупреждение о линтере или отключить его. По моему мнению, альтернативные подходы гораздо более читабельны, особенно slices.Concat.

Возможно, это только я, но когда вы предлагали food := slices.Concat(fruits, vegetables), я ошибочно ожидал, что slices.Concat не изменит базовый фрагмент, поэтому food := slices.Concat(fruits[:2], vegetables) будет «безопасная» альтернатива, оставляющая fruits нетронутым при копировании.

NotX 29.06.2024 16:22
slices.Concat не изменяет базовый массив он возвращает новый фрагмент, как указано в документации. slices.Concat(fruits[:2], vegetables) безопасно.
eik 29.06.2024 16:26

Ох, моя вина! Шутка ли, я даже на игровой площадке тестировал и не туда посмотрел результат.

NotX 29.06.2024 16:28

Другие вопросы по теме