Что такое Android Go? Смартфоны, которые его поддерживают
Компания Google постоянно совершенствует свою мобильную операционную систему. Основная версия Android требует уже достаточно неплохих характеристик от устройства, на котором она запускается. Но зато производитель ничем не ограничен, как и покупатель девайса. Но в 2017 году стало известно о разработке усечённой версии, получившей название Android Go. Чем она отличается от Android 8.0 Oreo?
В чём именно заключаются ограничения? На каких аппаратах будет присутствовать данная версия ОС? На все эти вопросы постарается ответить данная статья.
Чуть-чуть истории
В своё время компания Google уже занималась делением своей операционной системы. Достаточно вспомнить Android 3.0 и несколько последующих версий — они были предназначены только для планшетов, тогда как на смартфонах использовалась лишь «двойка». В этот же раз ситуация похожая, только нумерацию поисковый гигант менять не стал. Вместо этого упрощенная версия операционной системы, предназначенная для устройств со слабыми характеристиками, получила официальное название Android Oreo (Go edition).
Изучаем Go. Карты в Go. Maps in Go. Программирование на Go #5
А что означает приставка «Go» ? На этот вопрос ответить сложнее. В США такую приставку получают легкие в освоении мультимедиа-проекты. Например, ничего сложного нет в Pokemon Go — ходи себе по улице, да лови и расти карманных монстров. Также существуют игры Lara Croft Go и Hitman Go, являющиеся чем-то вроде раннера. Словом, наименование Android Go тоже подразумевает, что операционная система окажется легка в освоении, а смартфоны на её базе окажутся очень недорогими.
Зачем нужна ОС Android Go?
Выпуск облегченной версии «зеленого робота» был, если вдуматься, неминуем. Дело в том, что мобильная операционная система в последнее время стала чересчур насыщенной всевозможными функциями. Да ещё и сами производители смартфонов создают собственные фирменные оболочки, которые наделены дополнительными возможностями.
Всё это повышает минимальные требования к аппаратной платформе. Мы уже пришли к моменту, когда 2 Гб оперативной памяти — это сущий минимум, которого может не хватить для некоторых особо тяжелых игр. Ну а 16 Гб постоянной памяти — это вообще курам на смех. С таким объемом гарантированы скорые проблемы с обновлением приложений и установкой новых программ.
Раньше расширение функционала не вызывало особых проблем. Дело в том, что долгое время комплектующие для смартфонов и планшетов только дешевели. Однако в последнюю пару лет ситуация изменилось. Во-первых, снижение стоимости компонентов практически прекратилось, либо очень сильно снизилось.
Во-вторых, память в некоторые моменты даже дорожала (в расчёте «количество долларов за гигабайт»)! Именно поэтому компания Google решила дать своим партнерам возможность создания смартфонов со слабыми комплектующими. Для этого была разработана версия Android Oreo (Go edition).
Многочисленные упрощения
Казалось бы, что может быть сложного в упрощении операционной системы? Просто выкиньте какие-нибудь компоненты, которые редко используются людьми, а также устраните поддержку каких-нибудь не особо востребованных технологий, и на этом всё. Но в случае с Android не всё так просто.
Как работать с Google Maps
Вы можете об этом даже не подозревать, но наибольший объем оперативной памяти в вашем смартфоне занимают не исполнительные файлы операционной системы. Транжирят ОЗУ по максимуму приложения, разработанные компанией Google и предустанавливаемые сейчас на 99% смартфонов. Речь идет о Gmail, Google Maps, Youtube и многих других. Уж очень многофункциональными они стали, при этом практически все эти программы работают в фоне. А если производитель решил установить «Google Ассистент» (пока он не входит в пакет обязательных приложений), то ему предстоит встроить как минимум 3 Гб оперативной памяти.
Почему же Android Go появился только сейчас? Дело в том, что для его создания пришлось переработать не столько самого «зеленого робота», сколько предустанавливаемые программы. Практически все они в облегченной версии операционной системы тоже получили приставку «Go». Переработан был даже Play Store — пользователю здесь в первую очередь будут предлагаться облегченные версии приложений, среди которых уже есть, например, Skype. В остальном магазин почти не изменился — может быть, лишь сокращено количество категорий.
В целом продвинутый функционал из Android Go действительно убран. Но операционная система всё ещё ощущается как Android Oreo. Предпринятые действия позволили разработчикам вдвое сократить общий объем всех файлов, входящих в состав операционки. В результате смартфон с Android Go на борту может иметь всего 8 Гб встроенной памяти — этого пользователю всё равно хватит.
Что касается оперативной памяти, то её может быть всего 1 Гб, а в теории новую версию ОС можно запустить даже на устройствах с 512 Мб ОЗУ. И, конечно же, производителям не позволят устанавливать фирменную оболочку, которая свела бы преимущества Android Go на нет.
Из других особенностей облегченной версии ОС следует выделить активированную функцию экономии трафика. Также в компании Google заявляют, что приложения теперь открываются на 15% быстрее. Касается это абсолютно всех программ, а не только адаптированных для Android Go.
Приложения
Как уже сказано выше, разработчики из Google облегчили многие свои творения. В результате практически каждая программа занимает в два раза меньше места. При этом нельзя сказать, что это было достигнуто только за счет сокращения функционала. В основном выбор падал на устранение каких-то сложных визуальных эффектов.
На смартфоне с Android Go точно будут присутствовать YouTube Go и Google Maps Go. Также покупателю устройства предстоит использование приложения Files Go. Как несложно догадаться, это обычный файловый менеджер, заточенный под регулярное высвобождение памяти для хранения данных. Другой новой программой является Google Go — она предназначена для ускорения поиска информации и GIF-анимаций.
К слову, более быстрый ввод текста обеспечивает и предустановленная клавиатура, тоже получившая ряд изменений. Наконец, впервые на бюджетных смартфонах сможет работать «Google Ассистент». Благодаря некоторым упрощениям, голосовой помощник сможет функционировать на девайсе даже в том случае, если он оснащен всего 1 Гб оперативной памяти.
Источник: dzen.ru
Хэш таблицы в Go. Детали реализации
Порассуждаем об имплементации map в языке без дженериков, рассмотрим что такое хэш таблица, как она устроена в Go, какие есть плюсы и минусы данной реализации и на что стоит обратить внимание при использовании данной структуры.
Детали под катом.
Внимание! Кто уже знаком с хэш-таблицами в Go, советую пропустить основы и отправиться сюда, иначе есть риск устать к самому интересному моменту.
Что такое хэш таблица
Для начала все-таки напомню, что такое хэш таблица. Это структура данных, которая позволяет хранить пары ключ-значение, и, как правило, обладающая функциями:
- Маппинга: map(key) → value
- Вставки: insert(map, key, value)
- Удаления: delete(map, key)
- Поиска: lookup(key) → value
Хэш таблица в языке go
Хэш таблица в языке go представлена ключевым словом map и может быть объявлена одним из способов ниже (подробнее о них позже):
m := make(map[key_type]value_type) m := new(map[key_type]value_type) var m map[key_type]value_type m := map[key_type]value_type
Основные операции производятся так:
m[key] = value
delete(m, key)
value = m[key]
value, ok = m[key]
Обход таблицы в go
Рассмотрим следующую программу:
package main import «fmt» func main() < m := map[int]bool<>for i := 0; i < 5; i++ < m[i] = ((i % 2) == 0) >for k, v := range m < fmt.Printf(«key: %d, value: %tn», k, v) >>
key: 3, value: false key: 4, value: true key: 0, value: true key: 1, value: false key: 2, value: true
key: 4, value: true key: 0, value: true key: 1, value: false key: 2, value: true key: 3, value: false
Как видим, вывод разнится от запуска к запуску. А все потому, что мапа в Go unordered, то есть не упорядоченная.
Это значит, что полагаться на порядок при обходе не надо. Причину можно найти в исходном коде рантайма языка:
// mapiterinit initializes the hiter struct used for ranging over maps. func mapiterinit(t *maptype, h *hmap, it *hiter)
Место поиска определяется рандомно, запомните это! Ходят слухи, что так разработчики рантайма заставляют пользователей не полагаться на порядок.
Поиск в таблице Go
Снова рассмотрим кусок кода. Предположим, мы хотим создать пары «число»-«число умноженное на 10»:
package main import ( «fmt» ) func main() < m := map[int]intfmt.Println(m, m[0], m[1], m[2]) >
map[0:0 1:10] 0 10 0
И видим, что при попытке получить значение двойки (которую забыли положить) получили 0. Находим в документации строки, объясняющие это поведение: «An attempt to fetch a map value with a key that is not present in the map will return the zero value for the type of the entries in the map.», а в переводе на русский это означает, что когда мы пытаемся получить значение из мапы, а его там нет, получаем «нулевое значение типа», что в случае числа 0. Что же делать, если мы хотим различать случаи 0 и отсутствия 2? Для этого придумали специальную форму «multiple assignment» — форма, когда вместо привычного одного значения мапа возвращает пару: само значение и еще одно булевое, отвечающее на вопрос, присутствует ли запрошенный ключ в мапе или нет»
Правильно предыдущий кусок кода будет выглядеть так:
package main import ( «fmt» ) func main() < m := map[int]intm2, ok := m[2] if !ok < // somehow process this case m2 = 20 >fmt.Println(m, m[0], m[1], m2) >
И при запуске получим:
map[0:0 1:10] 0 10 20
Создание таблицы в Go.
Допустим, мы хотим посчитать количество вхождений каждого слова в строке, заведем для этого словарь и пройдемся по нему.
package main func main() < var m map[string]int for _, word := range []string < m[word]++ >for k, v := range m < println(k, v) >>
Вы гофера подвох видите? — А он есть!
При попытке запуска такой программы получим панику и сообщение «assignment to entry in nil map». А все потому что мапа — ссылочный тип и мало объявить переменную, надо ее проинициализировать:
m := make(map[string]int)
Чуть пониже будет понятно почему это работает именно так. В начале было представлено аж 4 способа создания мапы, два из них мы рассмотрели — это объявление как переменную и создание через make. Еще можно создать с помощью «Composite literals» конструкции
map[key_type]value_type<>
и при желании даже сразу проинициализировать значениями, этот способ тоже валидный. Что касается создания с помощью new — на мой взгляд, оно не имеет смысла, потому что эта функция выделяет память под переменную и возвращает указатель на нее, заполненную zero value типа, что в случае с map будет nil (мы получим тот же результат, что в var, точнее указатель на него).
Как передается map в функцию?
Допустим у нас есть функция, которая пытается поменять число, которое ей передали. Посмотрим, что будет до и после вызова:
package main func foo(n int) < n = 10 >func main() < n := 15 println(«n before foo =», n) foo(n) println(«n after foo plaintext»>n before foo = 15 n after foo = 15
Как вы наверное догадались, в функцию n пришло по значению, а не по ссылке, поэтому исходная переменная не поменялась.
Проделаем похожий трюк с мапой:
package main func foo(m map[int]int) < m[10] = 10 >func main() < m := make(map[int]int) m[10] = 15 println(«m[10] before foo =», m[10]) foo(m) println(«m[10] after foo go»>m[10] before foo = 15 m[10] after foo = 10
Значение поменялось. «Что же, мапа передается по ссылке?», — спросите вы. Нет. В Go не бывает ссылок. Невозможно создать 2 переменные с 1 адресом, как в С++ например.
Но зато можно создать 2 переменные, указывающие на один адрес (но это уже указатели, и они в Go есть).
Пусть у нас есть функция fn, которая инициализирует мапу m. В основной функции мы просто объявляем переменную, отправляем на инициализацию и смотрим что получилось после.
package main import «fmt» func fn(m map[int]int) < m = make(map[int]int) fmt.Println(«m == nil in fn?:», m == nil) >func main()
m == nil in fn?: false
m == nil in main?: true
Итак, переменная m передалась по значению, поэтому, как в случае с передачей в функцию обычного int, не поменялась (поменялась локальная копия значения в fn). Тогда почему же меняется значение, лежащее в самой m? Для ответа на этот вопрос рассмотрим код из рантайма языка:
// A header for a Go map. type hmap struct < // Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go. // Make sure this stays in sync with the compiler’s definition. count int // # live cells == size of map. Must be first (used by len() builtin) flags uint8 B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items) noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details hash0 uint32 // hash seed buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0. oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated) extra *mapextra // optional fields >
Мапа в Go — это просто указатель на структуру hmap. Это и является ответом на вопрос, почему при том, что мапа передается в функцию по значению, сами значения, лежащие в ней меняются — все дело в указателе. Так же структура hmap содержит в себе следующее: количество элементов, количество «ведер» (представлено в виде логарифма для ускорения вычислений), seed для рандомизации хэшей (чтобы было сложнее заddosить — попытаться подобрать ключи так, что будут сплошные коллизии), всякие служебные поля и главное указатель на buckets, где хранятся значения. Давайте посмотрим на рисунок:
На картинке схематичное изображение структуры в памяти — есть хэдер hmap, указатель на который и есть map в Go (именно он создается при объявлении с помощью var, но не инициализируется, из-за чего падает программа при попытке вставки). Поле buckets — хранилище пар ключ-значение, таких «ведер» несколько, в каждом лежит 8 пар. Сначала в «ведре» лежат слоты для дополнительных битов хэшей (e0..e7 названо e — потому что extra hash bits). Далее лежат ключи и значения как сначала список всех ключей, потом список всех значений.
По хэш функции определяется в какое «ведро» мы кладем значение, внутри каждого «ведра» может лежать до 8 коллизий, в конце каждого «ведра» есть указатель на дополнительное, если вдруг предыдущее переполнилось.
Как растет map?
В исходном коде можно найти строчку:
// Maximum average load of a bucket that triggers growth is 6.5.
то есть, если в каждом «ведре» в среднем более 6,5 элементов, происходит увеличение массива buckets. При этом выделяется массив в 2 раза больше, а старые данные копируются в него маленькими порциями каждые вставку или удаление, чтобы не создавать очень крупные задержки. Поэтому все операции будут чуть медленнее в процессе эвакуации данных (при поиске тоже, нам же приходится искать в двух местах). После успешной эвакуации начинают использоваться новые данные.
Взятие адреса элемента map.
Еще один достаточно интересный момент — мне в самом начале использования языка хотелось сделать вот так:
package main import ( «fmt» ) func main()
Но Go говорит: «cannot take the address of m[1]». Объяснение почему же нельзя взять адрес значения кроется процедуре эвакуации данных. Представьте, что мы взяли адрес значения, а потом мапа выросла, выделилась новая память, данные эвакуировались, старые удалились, указатель стал неправильным, поэтому такие операции запрещены.
Как реализована map без genericов?
Ни пустой интерфейс, ни кодогенерация тут ни при чем, все дело в замене во время компиляции. Рассмотрим во что превращаются знакомые нам функции из Go:
v := m[«k»] → func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer v, ok := m[«k»] → func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool) m[«k»] = 9001 → func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer delete(m, «k») → func mapdelete(t *maptype, h *hmap, key unsafe.Pointer)
Мы видим, что для доступов есть функции mapaccess, для записи и удаления mapassign и mapdelete соответственно. Все операции используют unsafe.Pointer, которому все равно, на какой тип он указывает, а информация о каждом значении описывается дескриптором типа.
type mapType struct < key *_type elem *_type . >type _type struct < size uintptr alg *typeAlg . >type typeAlg struct
В mapType хранятся дескрипторы (_type) ключа и значения. Для дескриптора типа определены операции (typeAlg) сравнения, взятия хэша, размера и так далее, поэтому мы всегда знаем как произвести их.
Немного поподробнее о том как это работает. Когда мы пишем v = m[k] (пытаемся получить значение v по ключу k), компилятор генерирует примерно следующее:
kPointer := unsafe.Pointer( (1<> 56) // extra := top 8 bits of hash b := (*bucket)(add(m.buckets, bucket*t.bucketsize)) // b := for i := 0; i < 8; i++ < if b.extra[i] != extra < // check 8 extra hash bits continue >k := add(b, dataOffset+i*t.key.size) // pointer to ki in bucket if t.key.equal(key, k) < // return pointer to vi return add(b, dataOffset+8*t.key.size+i*t.value.size) >> b = b.overflow if b == nil < return zero >>
Поиск, если разобраться, устроен не так уж и сложно: проходимся по цепочкам «ведер», переходя в следующее, если в этом не нашли.
Поиск в «ведре» начинается с быстрого сравнения дополнительного хэша (вот для чего эти e0. e7 в начале каждого — это «мини» хэш пары для быстрого сравнения). Если не совпало, идем дальше, если совпало, то проверяем тщательнее — определяем где лежит в памяти ключ, подозреваемый как искомый, сравниваем равен ли он тому, что запросили. Если равен, определяем положение значения в памяти и возвращаем. Как видите, ничего сверхъестественного.
Заключение
Используйте мапы, но знайте и понимайте как они работают! Можно избежать граблей, поняв некоторые тонкости — почему нельзя взять адрес значения, почему все падает при объявлении без инициализации, почему лучше выделить память заранее, если известно количество элементов (избежим эвакуаций) и многое другое.
Источник: habr.com
Основы работы с картами в Go
Большинство современных языков программирования поддерживают такие типы данных, как словарь или хэш. Эти типы обычно используются для хранения данных в парах, где ключ сопоставляется со значением.
В Go есть похожий тип данных – карты, большинство программистов считают его аналогом словаря. Он сопоставляет ключи со значениями, создавая пары «ключ-значение», это удобный способ хранения данных в Go. Карта создается с помощью ключевого слова map, за которым следует ключевой тип данных в квадратных скобках [] и значения. Пары «ключ-значение» помещаются с обеих сторон в фигурные скобки <>, вот так:
Обычно карты в Go используются для хранения связанных данных, например, идентификаторов. Карта с данными выглядит так:
Кроме фигурных скобок карта также содержит двоеточия, которые соединяют ключ и значение в пару. Слова слева от двоеточия являются ключами. Ключи в Go могут выражаться данными любого сопоставимого типа, например, строками, целыми числами и т.п.
В этом случае ключами являются:
- “name”
- “animal”
- “color”
- “location”
Слова справа от двоеточия являются значениями. Значения могут выражаться данными любого типа. В этом случае значениями являются:
Как и другие типы данных, карту можно сохранить внутри переменной и вывести ее на экран:
Вы получите такой вывод:
map[animal:shark color:blue location:ocean name:Sammy]
Порядок пар ключ-значение мог измениться. В Go карты – неупорядоченный тип данных. Независимо от порядка сами пары ключ-значение не меняются, что позволяет получать доступ к данным на основе их реляционного значения.
Доступ к элементам карты
Вызвать значение карты можно, сославшись на связанный ключ.
Вернемся к нашему примеру. Если вы хотите изолировать имя пользователя, вы можете сделать это, вызвав sammy[“name”]; – то есть переменную, содержащую карту и связанный ключ. Давайте сделаем это:
Карты ведут себя примерно как база данных; чтобы получить конкретное значение индекса, не нужно вызывать целое число, как в срезах, можно присвоить ключу значение и вызвать этот ключ, чтобы получить связанное с ним значение.
Вызывая ключ “name”, вы получаете значение этого ключа – “Sammy”.
Точно так же можно вызвать оставшиеся значения в карте sammy, используя тот же формат:
fmt.Println(sammy[«animal»])
// returns shark
fmt.Println(sammy[«color»])
// returns blue
fmt.Println(sammy[«location»])
// returns ocean
В картах можно ссылаться на ключи для получения значений.
Ключи и значения
В отличие от некоторых языков программирования, в Go нет удобных функций для получения ключей или значений карты. Например, в Python для словарей есть метод .keys(). Хотя Go допускает итерацию с помощью оператора range:
for key, value := range sammy fmt.Printf(«%q is the key for the value %qn», key, value)
>
При итерации по карте Go вернет два значения. Первым будет ключ, а вторым – значение. Go создаст эти переменные в правильном типе данных. В этом случае ключевым типом карты является строка, поэтому и ключ, и значение также будет выражаться строкой.
«animal» is the key for the value «shark»
«color» is the key for the value «blue»
«location» is the key for the value «ocean»
«name» is the key for the value «Sammy»
Чтобы получить список ключей, вы можете снова использовать оператор range. Вы можете объявить одну переменную, чтобы получить доступ только к ключам:
keys := []string<>
for key := range sammy keys = append(keys, key)
>
fmt.Printf(«%q», keys)
Программа начинается с объявления среза для хранения ключей.
Вывод покажет только ключи вашей карты:
[«color» «location» «name» «animal»]
Опять же, ключи не отсортированы. Если вы хотите отсортировать их, используйте функцию sort.Strings из пакета sort:
С помощью этой функции вы получите следующий вывод:
[«animal» «color» «location» «name»]
Вы можете использовать тот же шаблон, чтобы извлечь только значения карты. В следующем примере срез был предварительно создан, чтобы избежать выделения, это сделает программу более эффективной:
Сначала нужно объявить фрагмент для хранения ключей; так как вы знаете, сколько элементов вам нужно, вы можете избежать потенциального выделения памяти, определив срез необходимого размера. Затем объявляется переменная индекса. Поскольку ключи вам не нужны, вы можете использовать оператор _ при запуске цикла, чтобы игнорировать значение ключа. Вывод будет выглядеть так:
[«ocean» «Sammy» «shark» «blue»]
Чтобы определить количество элементов в карте, вы можете использовать встроенную функцию len:
Вывод покажет количество элементов в карте:
Хотя в Go нет удобных функций для получения списков ключей и значений, при необходимости достаточно написать всего несколько строк кода.
Проверка наличия данных
Карты в Go возвращают нулевое значение, если запрошенный ключ отсутствует. Поэтому нужен альтернативный способ, который позволил бы отличить действительное значение 0 от ключа, которого нет в карте.
Запросите такое значение в карте, которого не существует, и посмотрите на полученный результат:
counts := map[string]int<>
fmt.Println(counts[«sammy»])
Вы увидите следующий вывод:
Ключа sammy не было в карте, а Go все равно выдал его значение – 0. Это связано с тем, что типом данных для значений является int, а Go присваивает нулевое значение всем переменным.
Во многих случаях это поведение нежелательно и может привести к ошибке в программе. При поиске значения в карте Go может вернуть второе, опциональное значение. Это второе значение является логическим (bool) – это будет true, если ключ был найден, и false, если нет. В Go это называется идиомой ok. Несмотря на то, что назвать переменную, которая захватывает второй аргумент, можно было бы как угодно, в Go она всегда называется ok:
count, ok := counts[«sammy»]
Если ключ sammy существует в карте counts, тогда ok будет true. В противном случае будет false.
Вы можете использовать переменную ok, чтобы решить, что делать с вашей программой:
if ok fmt.Printf(«Sammy has a count of %dn», count)
> else fmt.Println(«Sammy was not found»)
>
Sammy was not found
В Go вы можете объединить объявление переменной и условную проверку с блоком if/else. Go позволяет использовать для этой проверки один оператор:
if count, ok := counts[«sammy»]; ok fmt.Printf(«Sammy has a count of %dn», count)
> else fmt.Println(«Sammy was not found»)
>
При извлечении значения из карты в Go всегда рекомендуется проверять его наличие, чтобы избежать ошибок в вашей программе.
Изменение карт
Карты являются изменяемой структурой данных, поэтому вы можете вносить в них поправки. Рассмотрим добавление и удаление элементов карты.
Добавление и изменение элементов карты
В карты можно добавлять пары ключ-значение без метода или функции. Это делается с помощью имени переменной карты, за которым следует значение ключа в квадратных скобках [], и с помощью оператора = для установки нового значения:
Попробуйте для практики добавить в карту пару ключ-значение usernames:
В выводе появится новая пара ключ-значение Drew:squidly:
map[Drew:squidly Jamie:mantisshrimp54 Sammy:sammy-shark]
Поскольку карты неупорядоченные, эта пара может встретиться в любом месте вывода карты. Если вы позже используете карту usernames в файле программы, она будет включать дополнительную пару ключ-значение.
Вы также можете использовать этот синтаксис для изменения значения, присвоенного ключу. В этом случае нужно сослаться на существующий ключ и передать ему другое значение.
Рассмотрим карту под названием followers, которая отслеживает подписчиков пользователей в данной сети. У пользователя “drew” сегодня добавились подписчики, поэтому нужно обновить целочисленное значение, передаваемое ключу “drew”. Используйте функцию Println(), чтобы проверить, была ли карта изменена:
followers := map[string]int
followers[«drew»] = 342
fmt.Println(followers)
Ваш вывод покажет обновленное значение для drew:
map[cindy:918 drew:342 mary:428]
Как можно видеть, число подписчиков подскочило с 305 до 342.
Вы можете использовать этот метод для добавления в карты пар ключ-значение с пользовательским вводом. Давайте напишем быструю программу под названием usernames.go, которая запускается в командной строке и позволяет вводить настоящие имена пользователей и связывать их с учетными данными:
В usernames.go мы сначала определили исходную карту. Затем мы настроили цикл для перебора имен. Программа просит пользователя ввести имя и объявляет переменную для его сохранения. Затем мы проверяем, не возникла ли ошибка; если да, программа прекратит работу (panic). Поскольку Scanln захватывает весь ввод, включая возврат каретки, вам необходимо удалить из ввода все пробелы; это делается с помощью функции strings.TrimSpace.
Блок if проверяет, присутствует ли имя в карте, и возвращает результат. Если имя присутствует, блок затем возвращается к началу цикла. Если имя отсутствует на карте, программа предоставляет обратную связь пользователю, а затем запросит новое имя пользователя для заданного имени. Программа снова проверит, есть ли ошибка. Если ошибок нет, она обрезает возврат каретки, присваивает значение имени пользователя ключу, а затем сообщает о том, что данные были обновлены.
go run usernames.go
Вы получите такой вывод:
Enter a name:
Sammy
«sammy-shark» is the username of «Sammy»
Enter a name:
Jesse
I don’t have Jesse’s username, what is it?
JOctopus
Data updated.
Enter a name:
Когда вы закончите тестирование программы, нажмите CTRL+C, чтобы выйти.
Эта программа показывает, как вы можете изменять карты в интерактивном режиме. В этом конкретном случае как только вы выйдете из программы с помощью клавиш CTRL+C, вы потеряете все свои данные, если не настроите способ чтения и записи файлов.
Итак, теперь вы можете добавлять элементы в карты или изменять значения с помощью синтаксиса map[key] = value.
Удаление элементов карты
Вы также можете удалять элементы из карты.
Чтобы удалить пару ключ-значение, вы можете использовать встроенную функцию delete(). Первый аргумент – карта, из которой вы хотите удалить значение. Второй аргумент – это ключ, который вы удаляете:
Давайте определим карту permissions:
Допустим, право modify вам больше не нужно, поэтому его можно удалить со своей карты. Затем можно отобразить карту, чтобы убедиться, что пара была удалена:
Вывод подтвердит удаление:
map[1:read 2:write 4:delete 8:create]
Строка delete(permissions, 16) удаляет пару ключ-значение 16:”modify” из карты permissions.
Если вы хотите полностью очистить карту от значений, вы можете приравнять ее к пустой карте того же типа. Это создаст новую пустую карту, а старая карта будет удалена из памяти сборщиком мусора.
Давайте удалим все элементы в карте permissions:
permissions = map[int]string<>
fmt.Println(permissions)
Вывод показывает, что теперь у вас есть пустая карта без пар:
Поскольку карты являются изменяемым типом данных, в них можно добавлять, изменять и удалять элементы.
Источник: www.8host.com
City Maps 2Go: народные офлайн карты на все случаи жизни
Вот находитесь Вы в чужой стране. Нет, не в Украине или Белоруссии, а в стране дальнего зарубежья. Роуминг тут жутко дорогой и онлайн карты использовать не получится. Что делать? Скачать программу City Maps 2Go в любом кафе с бесплатным Wi-Fi!
В принципе эта программа платная. Однако допускается ее бесплатное использование не более, чем с пятью картами. Этого вполне достаточно для небольшого турне по пяти европейским городам.
В окне работы с картами (my maps) можно поискать и добавить новые карты. Их действительно много! Представлены почти все страны мира. Такое многообразие карт в приложении не будет для нас удивительным, если мы посмотрим информацию о программе.
Карты для City Maps 2Go берутся с хорошо известного ресурса OpenStreetMap. Наполнением этих карт занимаются пользователи. Поэтому карты и бесплатны. В этом есть свои плюсы и свои минусы.
Плюс очевидный — это огромный выбор карт, о котором я писал ранее. При рисовании карты используется принцип вики — зарегистрированные пользователи вносят изменения и могут исправлять ошибки других. Основными конкурентами сервиса являются Wikimapia и Google Map Maker. А в нашей стране сильным конкурентом сервиса является Народная карта Яндекса.
По субъективным ощущениям, в России народная карта Яндекса лучше детализирована, чем карты OpenStreetMap. Однако, если Вы соберетесь в Европу, ситуация будет обратная.
Минус использования данных с OpenStreetMap — качество карт сильно зависит от старания пользователей, а это значит, что в разных регионах качество наполнения и адекватности карт может сильно меняться.
И еще одно важное замечание по картам. Если будете искать карту какого-нибудь города нашей страны, то выбирайте сразу карту области. Так и карт будет меньше (в бесплатной версии, напомним, могут быть только пять).
Поиск по названию
В программе City Maps 2Go реализован поиск. Однако не ожидайте от нее поиска по категориям POI или по критерию ближайшего расположения. Это просто поиск по названию.
Зато поиск достаточно неплохо продуман. По слову «гале» находятся и вхождения в названиях на английском языке и в названиях на русском, что весьма удобно.
Закладки (Bookmarks) и метки (pins)
К любимым местам можно прикреплять метки (pins) и делать закладки. Для каждой такой метки можно указать свое название. Также ошибочную булавку на карте можно удалять. Закладки можно делать на организации или объекты, отмеченные на карте другими пользователями.
Отличие в том, что метки на карте носят технический характер, временный. Закладки наоборот собираются в отдельном окне (bookmarks) и носят более постоянный характер. Туда хорошо помещать места, которые Вы, к примеру, хотели бы посетить. Или свой отель, чтобы не искать каждый раз его по всей карте.
Статьи из Wikipedia
В City Maps 2Go есть еще одна забавная фишка. Она позволяет локально загружать статьи вики, относящиеся к объектам на карте. Данные для статей берутся из Wikipedia. В самом приложении эта функция называется Wiki+. Полноценное использование возможно только в платной версии.
В бесплатной версии City Maps 2Go можно скачать только одну статью.
Ближайшие точки интереса
City Maps 2Go умеет показывать ближайшие POI или места интереса по категориям.
Однако качество наполнения таких мест упирается в качество наполнения самого ресурса OpenStreetMap. Для одного города там могут быть десятки тысяч точек, а для другого пусто.
Заключение
City Maps 2Go относится к тем программам, которые надо обязательно иметь с собой при путешествиях по цивилизованным странам. Она не раз выручит Вас в сложных ситуациях даже когда на счету сотового оператора ноль и ближайший Wi-Fi неизвестно где.
Источник: myfreesoft.ru