Показаны сообщения с ярлыком nil в Golang. Показать все сообщения
Показаны сообщения с ярлыком nil в Golang. Показать все сообщения

четверг, 24 декабря 2020 г.

Go style guides: nil - это допустимый срез

nil - это допустимый срез длины 0. Это означает, что,

  • Вы не должны явно возвращать срез нулевой длины. Вместо этого верните nil.

    Менее удачный пример:

    if x == "" {
        return []int{}
    }
    

    Более удачный пример:

    if x == "" {
        return nil
    }
    

  • Чтобы проверить, пуст ли срез, всегда используйте len(s) == 0. Не проверяйте на nil.

    Менее удачный пример:

    func isEmpty(s []string) bool {
        return s == nil
    }
    

    Более удачный пример:

    func isEmpty(s []string) bool {
        return len(s) == 0
    }
    

  • Нулевое значение (срез, объявленный с помощью var) можно сразу использовать без make().

    Менее удачный пример:

    nums := []int{}
    // или, nums := make([]int)
    
    if add1 {
        nums = append(nums, 1)
    }
    
    if add2 {
        nums = append(nums, 2)
    }
    

    Более удачный пример:

    var nums []int
    
    if add1 {
        nums = append(nums, 1)
    }
    
    if add2 {
        nums = append(nums, 2)
    }
    

Помните, что, хотя это действительный срез, нулевой срез (nil slice) не эквивалентен выделенному срезу длины 0 - первый равен nil, а второй нет - и оба могут обрабатываться по-разному в разных ситуациях (например, при сериализации).


Читайте также:


вторник, 18 февраля 2020 г.

Почему nil может быть не равен nil в Golang

Почему в этом примере nil не равен nil?

func Foo() error {
    var err *os.PathError = nil
    // …
    return err
}

func main() {
    err := Foo()
    fmt.Println(err)        // <nil>
    fmt.Println(err == nil) // false
}

Ответ

Значение интерфейса равно nil, только если его значение и динамический тип равны nil. В приведенном выше примере Foo() возвращает [nil, *os.PathError], и мы сравниваем его с [nil, nil].

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

…
fmt.Println(err == (*os.PathError)(nil)) // true
…

Лучший подход

Чтобы избежать этой проблемы, используйте вместо этого переменную типа error, например именованное возвращаемое значение.

func Foo() (err error) {
    // …
    // err не назначен и имеет нулевое значение [nil, nil]
    return 
}

func main() {
    err := Foo()
    fmt.Println(err)        // <nil>
    fmt.Println(err == nil) // true
}

Рекомендация. Используйте встроенный тип интерфейса error, а не конкретный тип, для хранения и возврата значений ошибок.


Читайте также: