3 наиболее распространённых подводных камня в Go |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2020-06-05 14:01 Начиная изучение Go, многие сталкиваются с совершенно не очевидными моментами в этом языке. Рассмотрим три таких подводных камня в Go. 1. Range Начнем программирование на Go с основ. Функция type Animal struct { name string legs int } func main() { zoo := []Animal{ Animal{ "Dog", 4 }, Animal{ "Chicken", 2 }, Animal{ "Snail", 0 }, } fmt.Printf("-> Before update %v ", zoo) for _, animal := range zoo { // ? Oppps! `animal` is a copy of an element ? animal.legs = 999 } fmt.Printf(" -> After update %v ", zoo) } Вышеприведённый код выглядит довольно невинно. Однако вы можете удивиться, узнав, что два -> Before update [{Dog 4} {Chicken 2} {Snail 0}] -> After update ??? [{Dog 4} {Chicken 2} {Snail 0}] Подводный камень Значения (хранятся как Решение Чтобы изменить элемент массива, мы должны изменить этот элемент через указатель: for idx, _ := range zoo { zoo[idx].legs = 999 } Возможно, это выглядит довольно тривиально, но вы можете быть удивлены, обнаружив, что это один из самых распространенных источников ошибок. 2. "…" и вариативные функции Быть может, вы использовали “…” в ЯП С для создания вариативной функции; вариативная функция – это функция, принимающая переменное количество аргументов. В C вы должны последовательно вызвать макрос int add_em_up (int count,...) { ... va_start (ap, count); /* Initialize the argument list */ for (i = 0; i < count; i++) sum += va_arg(ap, int); /* Get the next argument value */ va_end (ap); /* Clean up */ return sum } Программирование на Go задает несколько иные правила. В Golang это выглядит так же, как и в С, но работает по-другому. Здесь представлена вариативная функция func myFprint(format string, a ...interface{}) { if len(a) == 0 { fmt.Printf(format) } else { // ? `a` should be `a...` fmt.Printf(format, a) // ? fmt.Printf(format, a...) } } func main() { myFprint("%s : line %d ", "file.txt", 49) } [file.txt %!s(int=49)] : line %!d(MISSING) file.txt : line 49 Можно подумать, что компилятор выдал бы ошибку при неправильном использовании вариативных параметров. Но обратите внимание, как Подводный камень В Go вариативные параметры разделяются компилятором. Это означает, что вариативный аргумент // `a` is just a slice! for _, elem := range a { fmt.Println(elem) } 3. Слайсинг Продолжим изучение Go слайсингом. Если вы делали слайсинг в Python, то наверняка помните, что этот приём даёт вам новый список со ссылками на элементы. Это свойство позволяет использовать такой Python код: a = [1, 2, 3] b = a[:2] # ? a completely new list! b[0] = 999 >>> a [1, 2, 3] >>> b [999, 2] Если вы попробуете то же самое в Go, получите что-то другое: func main() { data := []int{1,2,3} slice := data[:2] slice[0] = 999 fmt.Println(data) fmt.Println(slice) } [999 2 3] [999 2] Подводный камень В Go слайс имеет тот же базовый массив и ёмкость, что и оригинал. В Golang если вы измените элемент в слайсе, исходное содержимое тоже будет изменено. Решение Если вы хотите получить независимый слайс, у вас есть два варианта: // Option #1 // appending elements to a nil slice // `...` changes slice to arguments for the variadic function `append` a := append([]int{}, data[:2]...) // Option #1 // Create slice with length of 2 // copy(dest, src) a := make([]int, 2) copy(a, data[:2]) И, согласно StackOverflow, append намного быстрее make. Материалы по теме: Источник: proglib.io Комментарии: |
|