[{"data":1,"prerenderedAt":3568},["ShallowReactive",2],{"content:\u002F01-basics\u002F01-scalar-types":3},{"title":4,"description":5,"path":6,"body":7},"Скалярные типы в Go","Go — язык со строгой статической типизацией, и понимание базовых типов — это фундамент, без которого сложно объяснить что угодно: от работы со слайсами до устройства строк. Начнём с самого простого и постепенно дойдём до нюансов, которые регулярно всплывают на собеседованиях.","\u002F01-basics\u002F01-scalar-types",{"type":8,"value":9,"toc":3546},"minimark",[10,13,16,21,24,184,203,316,319,321,325,335,390,393,395,399,417,467,474,573,580,582,584,596,662,665,667,671,683,719,739,753,853,859,861,865,868,915,934,939,1014,1020,1024,1191,1209,1213,1318,1322,1408,1424,1506,1510,1569,1572,1578,1743,1749,1793,1799,1801,1805,1808,1885,1896,2067,2069,2073,2085,2135,2138,2186,2200,2202,2206,2227,2263,2281,2305,2329,2352,2367,2388,2404,2427,2448,2468,2470,2475,2477,2482,2488,2494,2500,2650,2655,2663,2668,2721,2723,2728,2733,2738,2757,2762,2768,2772,3027,3029,3034,3039,3044,3052,3066,3070,3076,3089,3093,3372,3374,3378,3419,3492,3542],[11,12,5],"p",{},[14,15],"hr",{},[17,18,20],"h2",{"id":19},"целочисленные-типы","Целочисленные типы",[11,22,23],{},"Go предоставляет полный набор целочисленных типов с явным указанием размера:",[25,26,27,43],"table",{},[28,29,30],"thead",{},[31,32,33,37,40],"tr",{},[34,35,36],"th",{},"Тип",[34,38,39],{},"Размер",[34,41,42],{},"Диапазон",[44,45,46,61,74,87,100,112,124,136,148,161,172],"tbody",{},[31,47,48,55,58],{},[49,50,51],"td",{},[52,53,54],"code",{},"int8",[49,56,57],{},"8 бит",[49,59,60],{},"-128 … 127",[31,62,63,68,71],{},[49,64,65],{},[52,66,67],{},"int16",[49,69,70],{},"16 бит",[49,72,73],{},"-32 768 … 32 767",[31,75,76,81,84],{},[49,77,78],{},[52,79,80],{},"int32",[49,82,83],{},"32 бита",[49,85,86],{},"-2 147 483 648 … 2 147 483 647",[31,88,89,94,97],{},[49,90,91],{},[52,92,93],{},"int64",[49,95,96],{},"64 бита",[49,98,99],{},"-9.2×10¹⁸ … 9.2×10¹⁸",[31,101,102,107,109],{},[49,103,104],{},[52,105,106],{},"uint8",[49,108,57],{},[49,110,111],{},"0 … 255",[31,113,114,119,121],{},[49,115,116],{},[52,117,118],{},"uint16",[49,120,70],{},[49,122,123],{},"0 … 65 535",[31,125,126,131,133],{},[49,127,128],{},[52,129,130],{},"uint32",[49,132,83],{},[49,134,135],{},"0 … 4 294 967 295",[31,137,138,143,145],{},[49,139,140],{},[52,141,142],{},"uint64",[49,144,96],{},[49,146,147],{},"0 … 1.8×10¹⁹",[31,149,150,155,158],{},[49,151,152],{},[52,153,154],{},"int",[49,156,157],{},"32 или 64 бита*",[49,159,160],{},"зависит от платформы",[31,162,163,168,170],{},[49,164,165],{},[52,166,167],{},"uint",[49,169,157],{},[49,171,160],{},[31,173,174,179,181],{},[49,175,176],{},[52,177,178],{},"uintptr",[49,180,160],{},[49,182,183],{},"для хранения указателей",[11,185,186,188,189,191,192,194,195,199,200,202],{},[52,187,154],{}," и ",[52,190,167],{}," — платформозависимые типы: на 64-битной системе это 64 бита, на 32-битной — 32. Важно понимать, что ",[52,193,154],{}," ",[196,197,198],"strong",{},"не является псевдонимом"," для ",[52,201,93],{}," — это самостоятельный тип, и компилятор не позволит их смешивать без явного приведения.",[204,205,210],"pre",{"className":206,"code":207,"language":208,"meta":209,"style":209},"language-go shiki shiki-themes github-dark","var a int = 10\nvar b int64 = 20\n\n\u002F\u002F Ошибка компиляции: cannot use b (type int64) as type int\n\u002F\u002F c := a + b\n\n\u002F\u002F Правильно — явное приведение\nc := a + int(b)\nfmt.Println(c) \u002F\u002F 30\n","go","",[52,211,212,234,249,256,263,269,274,280,300],{"__ignoreMap":209},[213,214,217,221,225,227,230],"span",{"class":215,"line":216},"line",1,[213,218,220],{"class":219},"snl16","var",[213,222,224],{"class":223},"s95oV"," a ",[213,226,154],{"class":219},[213,228,229],{"class":219}," =",[213,231,233],{"class":232},"sDLfK"," 10\n",[213,235,237,239,242,244,246],{"class":215,"line":236},2,[213,238,220],{"class":219},[213,240,241],{"class":223}," b ",[213,243,93],{"class":219},[213,245,229],{"class":219},[213,247,248],{"class":232}," 20\n",[213,250,252],{"class":215,"line":251},3,[213,253,255],{"emptyLinePlaceholder":254},true,"\n",[213,257,259],{"class":215,"line":258},4,[213,260,262],{"class":261},"sAwPA","\u002F\u002F Ошибка компиляции: cannot use b (type int64) as type int\n",[213,264,266],{"class":215,"line":265},5,[213,267,268],{"class":261},"\u002F\u002F c := a + b\n",[213,270,272],{"class":215,"line":271},6,[213,273,255],{"emptyLinePlaceholder":254},[213,275,277],{"class":215,"line":276},7,[213,278,279],{"class":261},"\u002F\u002F Правильно — явное приведение\n",[213,281,283,286,289,291,294,297],{"class":215,"line":282},8,[213,284,285],{"class":223},"c ",[213,287,288],{"class":219},":=",[213,290,224],{"class":223},[213,292,293],{"class":219},"+",[213,295,296],{"class":219}," int",[213,298,299],{"class":223},"(b)\n",[213,301,303,306,310,313],{"class":215,"line":302},9,[213,304,305],{"class":223},"fmt.",[213,307,309],{"class":308},"svObZ","Println",[213,311,312],{"class":223},"(c) ",[213,314,315],{"class":261},"\u002F\u002F 30\n",[11,317,318],{},"Эта строгость — намеренное решение. В C неявные преобразования между числовыми типами — источник целого класса багов. Go убирает проблему на уровне компилятора.",[14,320],{},[17,322,324],{"id":323},"нулевые-значения-zero-values","Нулевые значения (zero values)",[11,326,327,328,331,332,334],{},"Прежде чем двигаться дальше, стоит сразу усвоить одно из ключевых правил Go: ",[196,329,330],{},"в языке нет неинициализированных переменных",". Каждый тип имеет нулевое значение, которое присваивается автоматически при объявлении через ",[52,333,220],{},":",[204,336,338],{"className":206,"code":337,"language":208,"meta":209,"style":209},"var i int       \u002F\u002F 0\nvar f float64   \u002F\u002F 0.0\nvar b bool      \u002F\u002F false\nvar s string    \u002F\u002F \"\"\n",[52,339,340,352,365,377],{"__ignoreMap":209},[213,341,342,344,347,349],{"class":215,"line":216},[213,343,220],{"class":219},[213,345,346],{"class":223}," i ",[213,348,154],{"class":219},[213,350,351],{"class":261},"       \u002F\u002F 0\n",[213,353,354,356,359,362],{"class":215,"line":236},[213,355,220],{"class":219},[213,357,358],{"class":223}," f ",[213,360,361],{"class":219},"float64",[213,363,364],{"class":261},"   \u002F\u002F 0.0\n",[213,366,367,369,371,374],{"class":215,"line":251},[213,368,220],{"class":219},[213,370,241],{"class":223},[213,372,373],{"class":219},"bool",[213,375,376],{"class":261},"      \u002F\u002F false\n",[213,378,379,381,384,387],{"class":215,"line":258},[213,380,220],{"class":219},[213,382,383],{"class":223}," s ",[213,385,386],{"class":219},"string",[213,388,389],{"class":261},"    \u002F\u002F \"\"\n",[11,391,392],{},"Это не просто синтаксический сахар — это архитектурное решение. Вы всегда знаете, в каком состоянии находится переменная, даже если забыли её явно инициализировать. Концепция zero value пронизывает весь язык: структуры, слайсы, каналы — везде применяется один и тот же принцип.",[14,394],{},[17,396,398],{"id":397},"числа-с-плавающей-точкой","Числа с плавающей точкой",[11,400,401,402,188,405,407,408,413,414,416],{},"Разобравшись с целыми, перейдём к вещественным числам. Go предоставляет два типа: ",[52,403,404],{},"float32",[52,406,361],{},". ",[196,409,410,412],{},[52,411,361],{}," — тип по умолчанию"," для нетипизированных вещественных констант и предпочтителен в большинстве задач из-за точности. ",[52,415,404],{}," оправдан только там, где критична память — например, в больших числовых массивах или при работе с GPU.",[204,418,420],{"className":206,"code":419,"language":208,"meta":209,"style":209},"var f32 float32 = 3.14\nvar f64 float64 = 3.141592653589793\n\nf := 3.14       \u002F\u002F тип float64\n",[52,421,422,436,450,454],{"__ignoreMap":209},[213,423,424,426,429,431,433],{"class":215,"line":216},[213,425,220],{"class":219},[213,427,428],{"class":223}," f32 ",[213,430,404],{"class":219},[213,432,229],{"class":219},[213,434,435],{"class":232}," 3.14\n",[213,437,438,440,443,445,447],{"class":215,"line":236},[213,439,220],{"class":219},[213,441,442],{"class":223}," f64 ",[213,444,361],{"class":219},[213,446,229],{"class":219},[213,448,449],{"class":232}," 3.141592653589793\n",[213,451,452],{"class":215,"line":251},[213,453,255],{"emptyLinePlaceholder":254},[213,455,456,459,461,464],{"class":215,"line":258},[213,457,458],{"class":223},"f ",[213,460,288],{"class":219},[213,462,463],{"class":232}," 3.14",[213,465,466],{"class":261},"       \u002F\u002F тип float64\n",[11,468,469,470,473],{},"Здесь есть классическая ловушка, которая встречается на каждом втором собеседовании: сравнение через ",[52,471,472],{},"==",".",[204,475,477],{"className":206,"code":476,"language":208,"meta":209,"style":209},"a := 0.1\nb := 0.2\nc := 0.3\nfmt.Println(a+b == c)                    \u002F\u002F false (!)\nfmt.Println(math.Abs((a+b)-c) \u003C 1e-9)    \u002F\u002F true — правильный способ\n",[52,478,479,489,499,508,529],{"__ignoreMap":209},[213,480,481,484,486],{"class":215,"line":216},[213,482,483],{"class":223},"a ",[213,485,288],{"class":219},[213,487,488],{"class":232}," 0.1\n",[213,490,491,494,496],{"class":215,"line":236},[213,492,493],{"class":223},"b ",[213,495,288],{"class":219},[213,497,498],{"class":232}," 0.2\n",[213,500,501,503,505],{"class":215,"line":251},[213,502,285],{"class":223},[213,504,288],{"class":219},[213,506,507],{"class":232}," 0.3\n",[213,509,510,512,514,517,519,521,523,526],{"class":215,"line":258},[213,511,305],{"class":223},[213,513,309],{"class":308},[213,515,516],{"class":223},"(a",[213,518,293],{"class":219},[213,520,493],{"class":223},[213,522,472],{"class":219},[213,524,525],{"class":223}," c)                    ",[213,527,528],{"class":261},"\u002F\u002F false (!)\n",[213,530,531,533,535,538,541,544,546,549,552,555,558,561,564,567,570],{"class":215,"line":265},[213,532,305],{"class":223},[213,534,309],{"class":308},[213,536,537],{"class":223},"(math.",[213,539,540],{"class":308},"Abs",[213,542,543],{"class":223},"((a",[213,545,293],{"class":219},[213,547,548],{"class":223},"b)",[213,550,551],{"class":219},"-",[213,553,554],{"class":223},"c) ",[213,556,557],{"class":219},"\u003C",[213,559,560],{"class":232}," 1",[213,562,563],{"class":219},"e-",[213,565,566],{"class":232},"9",[213,568,569],{"class":223},")    ",[213,571,572],{"class":261},"\u002F\u002F true — правильный способ\n",[11,574,575,576,579],{},"Числа с плавающей точкой хранятся в формате IEEE 754, и большинство десятичных дробей не имеют точного двоичного представления. ",[52,577,578],{},"0.1"," в двоичной системе — это бесконечная дробь, поэтому после арифметики накапливается ошибка представления. Это не баг Go — это фундаментальное ограничение формата, одинаковое для всех языков.",[14,581],{},[17,583,373],{"id":373},[11,585,586,588,589,188,592,595],{},[52,587,373],{}," в Go максимально лаконичен — только ",[52,590,591],{},"true",[52,593,594],{},"false",", никакого неявного приведения из других типов:",[204,597,599],{"className":206,"code":598,"language":208,"meta":209,"style":209},"var active bool        \u002F\u002F false\nisReady := true\n\n\u002F\u002F В отличие от C — if (1) {} в Go не скомпилируется\nif isReady {\n    fmt.Println(\"ready\")\n}\n",[52,600,601,613,623,627,632,640,657],{"__ignoreMap":209},[213,602,603,605,608,610],{"class":215,"line":216},[213,604,220],{"class":219},[213,606,607],{"class":223}," active ",[213,609,373],{"class":219},[213,611,612],{"class":261},"        \u002F\u002F false\n",[213,614,615,618,620],{"class":215,"line":236},[213,616,617],{"class":223},"isReady ",[213,619,288],{"class":219},[213,621,622],{"class":232}," true\n",[213,624,625],{"class":215,"line":251},[213,626,255],{"emptyLinePlaceholder":254},[213,628,629],{"class":215,"line":258},[213,630,631],{"class":261},"\u002F\u002F В отличие от C — if (1) {} в Go не скомпилируется\n",[213,633,634,637],{"class":215,"line":265},[213,635,636],{"class":219},"if",[213,638,639],{"class":223}," isReady {\n",[213,641,642,645,647,650,654],{"class":215,"line":271},[213,643,644],{"class":223},"    fmt.",[213,646,309],{"class":308},[213,648,649],{"class":223},"(",[213,651,653],{"class":652},"sU2Wk","\"ready\"",[213,655,656],{"class":223},")\n",[213,658,659],{"class":215,"line":276},[213,660,661],{"class":223},"}\n",[11,663,664],{},"Это ещё одно проявление философии языка: явное лучше неявного.",[14,666],{},[17,668,670],{"id":669},"byte-и-rune-псевдонимы-а-не-отдельные-типы","byte и rune — псевдонимы, а не отдельные типы",[11,672,673,674,188,677,680,681,473],{},"Понимание ",[52,675,676],{},"byte",[52,678,679],{},"rune"," критично для работы со строками, поэтому разберём их подробно, прежде чем перейти к ",[52,682,386],{},[204,684,686],{"className":206,"code":685,"language":208,"meta":209,"style":209},"type byte = uint8   \u002F\u002F псевдоним uint8\ntype rune = int32   \u002F\u002F псевдоним int32\n",[52,687,688,704],{"__ignoreMap":209},[213,689,690,693,696,698,701],{"class":215,"line":216},[213,691,692],{"class":219},"type",[213,694,695],{"class":219}," byte",[213,697,229],{"class":219},[213,699,700],{"class":219}," uint8",[213,702,703],{"class":261},"   \u002F\u002F псевдоним uint8\n",[213,705,706,708,711,713,716],{"class":215,"line":236},[213,707,692],{"class":219},[213,709,710],{"class":219}," rune",[213,712,229],{"class":219},[213,714,715],{"class":219}," int32",[213,717,718],{"class":261},"   \u002F\u002F псевдоним int32\n",[11,720,721,722,725,726,729,730,733,734,188,736,738],{},"Это именно ",[196,723,724],{},"псевдонимы"," (",[52,727,728],{},"=","), а не определения новых типов (",[52,731,732],{},"type byte uint8"," было бы другим). Это значит, что ",[52,735,676],{},[52,737,106],{}," — буквально одно и то же, компилятор не видит между ними разницы.",[740,741,742,748],"ul",{},[743,744,745,747],"li",{},[52,746,676],{}," используется при работе с бинарными данными, сетевыми протоколами и ASCII-строками. Он сигнализирует читателю кода: \"здесь мы работаем с байтами, а не символами\".",[743,749,750,752],{},[52,751,679],{}," представляет один Unicode code point — то, что в других языках называют \"символом\". Занимает 4 байта, что позволяет вместить весь Unicode (более 1 млн символов).",[204,754,756],{"className":206,"code":755,"language":208,"meta":209,"style":209},"var b byte = 'A'    \u002F\u002F 65\nvar r rune = 'Я'    \u002F\u002F 1071\n\nfmt.Printf(\"%T %v\\n\", b, b) \u002F\u002F uint8 65\nfmt.Printf(\"%T %v\\n\", r, r) \u002F\u002F int32 1071\n",[52,757,758,780,801,805,831],{"__ignoreMap":209},[213,759,760,762,764,766,768,771,774,777],{"class":215,"line":216},[213,761,220],{"class":219},[213,763,241],{"class":223},[213,765,676],{"class":219},[213,767,229],{"class":219},[213,769,770],{"class":652}," '",[213,772,773],{"class":232},"A",[213,775,776],{"class":652},"'",[213,778,779],{"class":261},"    \u002F\u002F 65\n",[213,781,782,784,787,789,791,793,796,798],{"class":215,"line":236},[213,783,220],{"class":219},[213,785,786],{"class":223}," r ",[213,788,679],{"class":219},[213,790,229],{"class":219},[213,792,770],{"class":652},[213,794,795],{"class":232},"Я",[213,797,776],{"class":652},[213,799,800],{"class":261},"    \u002F\u002F 1071\n",[213,802,803],{"class":215,"line":251},[213,804,255],{"emptyLinePlaceholder":254},[213,806,807,809,812,814,817,820,823,825,828],{"class":215,"line":258},[213,808,305],{"class":223},[213,810,811],{"class":308},"Printf",[213,813,649],{"class":223},[213,815,816],{"class":652},"\"",[213,818,819],{"class":232},"%T",[213,821,822],{"class":232}," %v\\n",[213,824,816],{"class":652},[213,826,827],{"class":223},", b, b) ",[213,829,830],{"class":261},"\u002F\u002F uint8 65\n",[213,832,833,835,837,839,841,843,845,847,850],{"class":215,"line":265},[213,834,305],{"class":223},[213,836,811],{"class":308},[213,838,649],{"class":223},[213,840,816],{"class":652},[213,842,819],{"class":232},[213,844,822],{"class":232},[213,846,816],{"class":652},[213,848,849],{"class":223},", r, r) ",[213,851,852],{"class":261},"\u002F\u002F int32 1071\n",[11,854,855,856,858],{},"С пониманием ",[52,857,679],{}," можно переходить к строкам — там это знание пригодится немедленно.",[14,860],{},[17,862,864],{"id":863},"string-неизменяемый-срез-байт","string — неизменяемый срез байт",[11,866,867],{},"Строки в Go устроены иначе, чем кажется на первый взгляд. Под капотом строка — это структура из двух полей:",[204,869,871],{"className":206,"code":870,"language":208,"meta":209,"style":209},"\u002F\u002F Внутреннее представление (из пакета reflect)\ntype StringHeader struct {\n    Data uintptr  \u002F\u002F указатель на массив байт в памяти\n    Len  int      \u002F\u002F длина в байтах, не в символах\n}\n",[52,872,873,878,891,901,911],{"__ignoreMap":209},[213,874,875],{"class":215,"line":216},[213,876,877],{"class":261},"\u002F\u002F Внутреннее представление (из пакета reflect)\n",[213,879,880,882,885,888],{"class":215,"line":236},[213,881,692],{"class":219},[213,883,884],{"class":308}," StringHeader",[213,886,887],{"class":219}," struct",[213,889,890],{"class":223}," {\n",[213,892,893,896,898],{"class":215,"line":251},[213,894,895],{"class":223},"    Data ",[213,897,178],{"class":219},[213,899,900],{"class":261},"  \u002F\u002F указатель на массив байт в памяти\n",[213,902,903,906,908],{"class":215,"line":258},[213,904,905],{"class":223},"    Len  ",[213,907,154],{"class":219},[213,909,910],{"class":261},"      \u002F\u002F длина в байтах, не в символах\n",[213,912,913],{"class":215,"line":265},[213,914,661],{"class":223},[11,916,917,918,921,922,925,926,929,930,933],{},"Два ключевых следствия из этого устройства. Первое: ",[52,919,920],{},"len()"," возвращает ",[196,923,924],{},"байты",", а не символы. Второе: строка ",[196,927,928],{},"неизменяема"," — данные, на которые указывает ",[52,931,932],{},"Data",", нельзя изменить.",[935,936,938],"h3",{"id":937},"байты-vs-символы-главная-ловушка","Байты vs символы — главная ловушка",[204,940,942],{"className":206,"code":941,"language":208,"meta":209,"style":209},"s := \"Привет\"\n\nfmt.Println(len(s))                    \u002F\u002F 12 — байты!\nfmt.Println(utf8.RuneCountInString(s)) \u002F\u002F 6  — символы\nfmt.Println(len([]rune(s)))            \u002F\u002F 6  — тоже символы, но с выделением памяти\n",[52,943,944,954,958,975,993],{"__ignoreMap":209},[213,945,946,949,951],{"class":215,"line":216},[213,947,948],{"class":223},"s ",[213,950,288],{"class":219},[213,952,953],{"class":652}," \"Привет\"\n",[213,955,956],{"class":215,"line":236},[213,957,255],{"emptyLinePlaceholder":254},[213,959,960,962,964,966,969,972],{"class":215,"line":251},[213,961,305],{"class":223},[213,963,309],{"class":308},[213,965,649],{"class":223},[213,967,968],{"class":308},"len",[213,970,971],{"class":223},"(s))                    ",[213,973,974],{"class":261},"\u002F\u002F 12 — байты!\n",[213,976,977,979,981,984,987,990],{"class":215,"line":258},[213,978,305],{"class":223},[213,980,309],{"class":308},[213,982,983],{"class":223},"(utf8.",[213,985,986],{"class":308},"RuneCountInString",[213,988,989],{"class":223},"(s)) ",[213,991,992],{"class":261},"\u002F\u002F 6  — символы\n",[213,994,995,997,999,1001,1003,1006,1008,1011],{"class":215,"line":265},[213,996,305],{"class":223},[213,998,309],{"class":308},[213,1000,649],{"class":223},[213,1002,968],{"class":308},[213,1004,1005],{"class":223},"([]",[213,1007,679],{"class":219},[213,1009,1010],{"class":223},"(s)))            ",[213,1012,1013],{"class":261},"\u002F\u002F 6  — тоже символы, но с выделением памяти\n",[11,1015,1016,1017,1019],{},"Кириллица в UTF-8 занимает по 2 байта на символ, поэтому \"Привет\" — это 6 символов и 12 байт. Эмодзи занимают 4 байта. Латиница — 1 байт. Вот почему наивный ",[52,1018,920],{}," обманывает.",[935,1021,1023],{"id":1022},"итерация-два-способа-с-разным-смыслом","Итерация: два способа с разным смыслом",[204,1025,1027],{"className":206,"code":1026,"language":208,"meta":209,"style":209},"s := \"Привет\"\n\n\u002F\u002F Итерация по байтам — неправильно для многобайтных символов\nfor i := 0; i \u003C len(s); i++ {\n    fmt.Printf(\"%x \", s[i]) \u002F\u002F c0 d0 d1 80 d0 b8 ...\n}\n\n\u002F\u002F Итерация по рунам через range — правильно\nfor i, r := range s {\n    fmt.Printf(\"[байт %d] = %c\\n\", i, r)\n}\n\u002F\u002F [байт 0] = П\n\u002F\u002F [байт 2] = р   \u003C-- прыжок на 2, а не на 1!\n\u002F\u002F [байт 4] = и\n\u002F\u002F [байт 6] = в\n\u002F\u002F [байт 8] = е\n\u002F\u002F [байт 10] = т\n",[52,1028,1029,1037,1041,1046,1074,1096,1100,1104,1109,1124,1150,1155,1161,1167,1173,1179,1185],{"__ignoreMap":209},[213,1030,1031,1033,1035],{"class":215,"line":216},[213,1032,948],{"class":223},[213,1034,288],{"class":219},[213,1036,953],{"class":652},[213,1038,1039],{"class":215,"line":236},[213,1040,255],{"emptyLinePlaceholder":254},[213,1042,1043],{"class":215,"line":251},[213,1044,1045],{"class":261},"\u002F\u002F Итерация по байтам — неправильно для многобайтных символов\n",[213,1047,1048,1051,1053,1055,1058,1061,1063,1066,1069,1072],{"class":215,"line":258},[213,1049,1050],{"class":219},"for",[213,1052,346],{"class":223},[213,1054,288],{"class":219},[213,1056,1057],{"class":232}," 0",[213,1059,1060],{"class":223},"; i ",[213,1062,557],{"class":219},[213,1064,1065],{"class":308}," len",[213,1067,1068],{"class":223},"(s); i",[213,1070,1071],{"class":219},"++",[213,1073,890],{"class":223},[213,1075,1076,1078,1080,1082,1084,1087,1090,1093],{"class":215,"line":265},[213,1077,644],{"class":223},[213,1079,811],{"class":308},[213,1081,649],{"class":223},[213,1083,816],{"class":652},[213,1085,1086],{"class":232},"%x",[213,1088,1089],{"class":652}," \"",[213,1091,1092],{"class":223},", s[i]) ",[213,1094,1095],{"class":261},"\u002F\u002F c0 d0 d1 80 d0 b8 ...\n",[213,1097,1098],{"class":215,"line":271},[213,1099,661],{"class":223},[213,1101,1102],{"class":215,"line":276},[213,1103,255],{"emptyLinePlaceholder":254},[213,1105,1106],{"class":215,"line":282},[213,1107,1108],{"class":261},"\u002F\u002F Итерация по рунам через range — правильно\n",[213,1110,1111,1113,1116,1118,1121],{"class":215,"line":302},[213,1112,1050],{"class":219},[213,1114,1115],{"class":223}," i, r ",[213,1117,288],{"class":219},[213,1119,1120],{"class":219}," range",[213,1122,1123],{"class":223}," s {\n",[213,1125,1127,1129,1131,1133,1136,1139,1142,1145,1147],{"class":215,"line":1126},10,[213,1128,644],{"class":223},[213,1130,811],{"class":308},[213,1132,649],{"class":223},[213,1134,1135],{"class":652},"\"[байт ",[213,1137,1138],{"class":232},"%d",[213,1140,1141],{"class":652},"] = ",[213,1143,1144],{"class":232},"%c\\n",[213,1146,816],{"class":652},[213,1148,1149],{"class":223},", i, r)\n",[213,1151,1153],{"class":215,"line":1152},11,[213,1154,661],{"class":223},[213,1156,1158],{"class":215,"line":1157},12,[213,1159,1160],{"class":261},"\u002F\u002F [байт 0] = П\n",[213,1162,1164],{"class":215,"line":1163},13,[213,1165,1166],{"class":261},"\u002F\u002F [байт 2] = р   \u003C-- прыжок на 2, а не на 1!\n",[213,1168,1170],{"class":215,"line":1169},14,[213,1171,1172],{"class":261},"\u002F\u002F [байт 4] = и\n",[213,1174,1176],{"class":215,"line":1175},15,[213,1177,1178],{"class":261},"\u002F\u002F [байт 6] = в\n",[213,1180,1182],{"class":215,"line":1181},16,[213,1183,1184],{"class":261},"\u002F\u002F [байт 8] = е\n",[213,1186,1188],{"class":215,"line":1187},17,[213,1189,1190],{"class":261},"\u002F\u002F [байт 10] = т\n",[11,1192,1193,1194,1197,1198,1201,1202,1205,1206,1208],{},"Обратите внимание: ",[52,1195,1196],{},"i"," в ",[52,1199,1200],{},"range"," — это ",[196,1203,1204],{},"байтовая позиция",", а не порядковый номер символа. ",[52,1207,1200],{}," по строке автоматически декодирует UTF-8 и возвращает руны.",[935,1210,1212],{"id":1211},"обращение-по-индексу-возвращает-байт-а-не-символ","Обращение по индексу возвращает байт, а не символ",[204,1214,1216],{"className":206,"code":1215,"language":208,"meta":209,"style":209},"s := \"Привет\"\nfmt.Println(s[0])          \u002F\u002F 208 — первый байт руны 'П', не сама 'П'\nfmt.Printf(\"%c\\n\", s[0])  \u002F\u002F Ð — мусор, потому что 208 — это не полный символ\n\n\u002F\u002F Правильно — получить руну по позиции\nrunes := []rune(s)\nfmt.Printf(\"%c\\n\", runes[0]) \u002F\u002F П\n",[52,1217,1218,1226,1244,1269,1273,1278,1293],{"__ignoreMap":209},[213,1219,1220,1222,1224],{"class":215,"line":216},[213,1221,948],{"class":223},[213,1223,288],{"class":219},[213,1225,953],{"class":652},[213,1227,1228,1230,1232,1235,1238,1241],{"class":215,"line":236},[213,1229,305],{"class":223},[213,1231,309],{"class":308},[213,1233,1234],{"class":223},"(s[",[213,1236,1237],{"class":232},"0",[213,1239,1240],{"class":223},"])          ",[213,1242,1243],{"class":261},"\u002F\u002F 208 — первый байт руны 'П', не сама 'П'\n",[213,1245,1246,1248,1250,1252,1254,1256,1258,1261,1263,1266],{"class":215,"line":251},[213,1247,305],{"class":223},[213,1249,811],{"class":308},[213,1251,649],{"class":223},[213,1253,816],{"class":652},[213,1255,1144],{"class":232},[213,1257,816],{"class":652},[213,1259,1260],{"class":223},", s[",[213,1262,1237],{"class":232},[213,1264,1265],{"class":223},"])  ",[213,1267,1268],{"class":261},"\u002F\u002F Ð — мусор, потому что 208 — это не полный символ\n",[213,1270,1271],{"class":215,"line":258},[213,1272,255],{"emptyLinePlaceholder":254},[213,1274,1275],{"class":215,"line":265},[213,1276,1277],{"class":261},"\u002F\u002F Правильно — получить руну по позиции\n",[213,1279,1280,1283,1285,1288,1290],{"class":215,"line":271},[213,1281,1282],{"class":223},"runes ",[213,1284,288],{"class":219},[213,1286,1287],{"class":223}," []",[213,1289,679],{"class":219},[213,1291,1292],{"class":223},"(s)\n",[213,1294,1295,1297,1299,1301,1303,1305,1307,1310,1312,1315],{"class":215,"line":276},[213,1296,305],{"class":223},[213,1298,811],{"class":308},[213,1300,649],{"class":223},[213,1302,816],{"class":652},[213,1304,1144],{"class":232},[213,1306,816],{"class":652},[213,1308,1309],{"class":223},", runes[",[213,1311,1237],{"class":232},[213,1313,1314],{"class":223},"]) ",[213,1316,1317],{"class":261},"\u002F\u002F П\n",[935,1319,1321],{"id":1320},"строка-неизменяема","Строка неизменяема",[204,1323,1325],{"className":206,"code":1324,"language":208,"meta":209,"style":209},"s := \"hello\"\n\u002F\u002F s[0] = 'H' \u002F\u002F Ошибка компиляции: cannot assign to s[0]\n\n\u002F\u002F Изменить можно только через конвертацию — и это копирование\nb := []byte(s)\nb[0] = 'H'\ns = string(b)\nfmt.Println(s) \u002F\u002F Hello\n",[52,1326,1327,1336,1344,1348,1353,1365,1385,1396],{"__ignoreMap":209},[213,1328,1329,1331,1333],{"class":215,"line":216},[213,1330,948],{"class":223},[213,1332,288],{"class":219},[213,1334,1335],{"class":652}," \"hello\"\n",[213,1337,1338,1341],{"class":215,"line":236},[213,1339,1340],{"class":261},"\u002F\u002F s[0] = 'H'",[213,1342,1343],{"class":261}," \u002F\u002F Ошибка компиляции: cannot assign to s[0]\n",[213,1345,1346],{"class":215,"line":251},[213,1347,255],{"emptyLinePlaceholder":254},[213,1349,1350],{"class":215,"line":258},[213,1351,1352],{"class":261},"\u002F\u002F Изменить можно только через конвертацию — и это копирование\n",[213,1354,1355,1357,1359,1361,1363],{"class":215,"line":265},[213,1356,493],{"class":223},[213,1358,288],{"class":219},[213,1360,1287],{"class":223},[213,1362,676],{"class":219},[213,1364,1292],{"class":223},[213,1366,1367,1370,1372,1375,1377,1379,1382],{"class":215,"line":271},[213,1368,1369],{"class":223},"b[",[213,1371,1237],{"class":232},[213,1373,1374],{"class":223},"] ",[213,1376,728],{"class":219},[213,1378,770],{"class":652},[213,1380,1381],{"class":232},"H",[213,1383,1384],{"class":652},"'\n",[213,1386,1387,1389,1391,1394],{"class":215,"line":276},[213,1388,948],{"class":223},[213,1390,728],{"class":219},[213,1392,1393],{"class":219}," string",[213,1395,299],{"class":223},[213,1397,1398,1400,1402,1405],{"class":215,"line":282},[213,1399,305],{"class":223},[213,1401,309],{"class":308},[213,1403,1404],{"class":223},"(s) ",[213,1406,1407],{"class":261},"\u002F\u002F Hello\n",[11,1409,1410,1411,188,1414,1201,1417,1420,1421,334],{},"Каждое ",[52,1412,1413],{},"[]byte(s)",[52,1415,1416],{},"string(b)",[196,1418,1419],{},"аллокация и копирование"," данных. В горячих путях, где строки собираются по частям, это критично. Используйте ",[52,1422,1423],{},"strings.Builder",[204,1425,1427],{"className":206,"code":1426,"language":208,"meta":209,"style":209},"var sb strings.Builder\nfor i := 0; i \u003C 5; i++ {\n    sb.WriteString(\"hello \")\n}\nresult := sb.String() \u002F\u002F единственная аллокация в конце\n",[52,1428,1429,1444,1468,1483,1487],{"__ignoreMap":209},[213,1430,1431,1433,1436,1439,1441],{"class":215,"line":216},[213,1432,220],{"class":219},[213,1434,1435],{"class":223}," sb ",[213,1437,1438],{"class":308},"strings",[213,1440,473],{"class":223},[213,1442,1443],{"class":308},"Builder\n",[213,1445,1446,1448,1450,1452,1454,1456,1458,1461,1464,1466],{"class":215,"line":236},[213,1447,1050],{"class":219},[213,1449,346],{"class":223},[213,1451,288],{"class":219},[213,1453,1057],{"class":232},[213,1455,1060],{"class":223},[213,1457,557],{"class":219},[213,1459,1460],{"class":232}," 5",[213,1462,1463],{"class":223},"; i",[213,1465,1071],{"class":219},[213,1467,890],{"class":223},[213,1469,1470,1473,1476,1478,1481],{"class":215,"line":251},[213,1471,1472],{"class":223},"    sb.",[213,1474,1475],{"class":308},"WriteString",[213,1477,649],{"class":223},[213,1479,1480],{"class":652},"\"hello \"",[213,1482,656],{"class":223},[213,1484,1485],{"class":215,"line":258},[213,1486,661],{"class":223},[213,1488,1489,1492,1494,1497,1500,1503],{"class":215,"line":265},[213,1490,1491],{"class":223},"result ",[213,1493,288],{"class":219},[213,1495,1496],{"class":223}," sb.",[213,1498,1499],{"class":308},"String",[213,1501,1502],{"class":223},"() ",[213,1504,1505],{"class":261},"\u002F\u002F единственная аллокация в конце\n",[935,1507,1509],{"id":1508},"передача-строки-это-копирование-заголовка-не-данных","Передача строки — это копирование заголовка, не данных",[204,1511,1513],{"className":206,"code":1512,"language":208,"meta":209,"style":209},"func printString(s string) {\n    fmt.Println(s)\n}\n\ns := \"очень длинная строка...\"\nprintString(s) \u002F\u002F копируется только StringHeader (16 байт), не сами данные\n",[52,1514,1515,1534,1542,1546,1550,1559],{"__ignoreMap":209},[213,1516,1517,1520,1523,1525,1529,1531],{"class":215,"line":216},[213,1518,1519],{"class":219},"func",[213,1521,1522],{"class":308}," printString",[213,1524,649],{"class":223},[213,1526,1528],{"class":1527},"s9osk","s",[213,1530,1393],{"class":219},[213,1532,1533],{"class":223},") {\n",[213,1535,1536,1538,1540],{"class":215,"line":236},[213,1537,644],{"class":223},[213,1539,309],{"class":308},[213,1541,1292],{"class":223},[213,1543,1544],{"class":215,"line":251},[213,1545,661],{"class":223},[213,1547,1548],{"class":215,"line":258},[213,1549,255],{"emptyLinePlaceholder":254},[213,1551,1552,1554,1556],{"class":215,"line":265},[213,1553,948],{"class":223},[213,1555,288],{"class":219},[213,1557,1558],{"class":652}," \"очень длинная строка...\"\n",[213,1560,1561,1564,1566],{"class":215,"line":271},[213,1562,1563],{"class":308},"printString",[213,1565,1404],{"class":223},[213,1567,1568],{"class":261},"\u002F\u002F копируется только StringHeader (16 байт), не сами данные\n",[11,1570,1571],{},"Строки дёшевы для передачи в функцию, потому что копируется только заголовок (указатель + длина = 16 байт на 64-битной системе). Сами байты остаются на месте. Это одна из причин, почему в Go не нужно передавать строки по указателю.",[935,1573,1575,1576],{"id":1574},"конкатенация-оператором","Конкатенация оператором ",[52,1577,293],{},[204,1579,1581],{"className":206,"code":1580,"language":208,"meta":209,"style":209},"s := \"Hello\" + \", \" + \"World\" \u002F\u002F три строки → одна аллокация (компилятор оптимизирует)\n\n\u002F\u002F Но в цикле — катастрофа\nresult := \"\"\nfor i := 0; i \u003C 1000; i++ {\n    result += \"x\" \u002F\u002F 1000 аллокаций и копирований!\n}\n\n\u002F\u002F Правильно\nvar sb strings.Builder\nfor i := 0; i \u003C 1000; i++ {\n    sb.WriteByte('x')\n}\nresult = sb.String()\n",[52,1582,1583,1606,1610,1615,1624,1647,1661,1665,1669,1674,1686,1708,1726,1730],{"__ignoreMap":209},[213,1584,1585,1587,1589,1592,1595,1598,1600,1603],{"class":215,"line":216},[213,1586,948],{"class":223},[213,1588,288],{"class":219},[213,1590,1591],{"class":652}," \"Hello\"",[213,1593,1594],{"class":219}," +",[213,1596,1597],{"class":652}," \", \"",[213,1599,1594],{"class":219},[213,1601,1602],{"class":652}," \"World\"",[213,1604,1605],{"class":261}," \u002F\u002F три строки → одна аллокация (компилятор оптимизирует)\n",[213,1607,1608],{"class":215,"line":236},[213,1609,255],{"emptyLinePlaceholder":254},[213,1611,1612],{"class":215,"line":251},[213,1613,1614],{"class":261},"\u002F\u002F Но в цикле — катастрофа\n",[213,1616,1617,1619,1621],{"class":215,"line":258},[213,1618,1491],{"class":223},[213,1620,288],{"class":219},[213,1622,1623],{"class":652}," \"\"\n",[213,1625,1626,1628,1630,1632,1634,1636,1638,1641,1643,1645],{"class":215,"line":265},[213,1627,1050],{"class":219},[213,1629,346],{"class":223},[213,1631,288],{"class":219},[213,1633,1057],{"class":232},[213,1635,1060],{"class":223},[213,1637,557],{"class":219},[213,1639,1640],{"class":232}," 1000",[213,1642,1463],{"class":223},[213,1644,1071],{"class":219},[213,1646,890],{"class":223},[213,1648,1649,1652,1655,1658],{"class":215,"line":271},[213,1650,1651],{"class":223},"    result ",[213,1653,1654],{"class":219},"+=",[213,1656,1657],{"class":652}," \"x\"",[213,1659,1660],{"class":261}," \u002F\u002F 1000 аллокаций и копирований!\n",[213,1662,1663],{"class":215,"line":276},[213,1664,661],{"class":223},[213,1666,1667],{"class":215,"line":282},[213,1668,255],{"emptyLinePlaceholder":254},[213,1670,1671],{"class":215,"line":302},[213,1672,1673],{"class":261},"\u002F\u002F Правильно\n",[213,1675,1676,1678,1680,1682,1684],{"class":215,"line":1126},[213,1677,220],{"class":219},[213,1679,1435],{"class":223},[213,1681,1438],{"class":308},[213,1683,473],{"class":223},[213,1685,1443],{"class":308},[213,1687,1688,1690,1692,1694,1696,1698,1700,1702,1704,1706],{"class":215,"line":1152},[213,1689,1050],{"class":219},[213,1691,346],{"class":223},[213,1693,288],{"class":219},[213,1695,1057],{"class":232},[213,1697,1060],{"class":223},[213,1699,557],{"class":219},[213,1701,1640],{"class":232},[213,1703,1463],{"class":223},[213,1705,1071],{"class":219},[213,1707,890],{"class":223},[213,1709,1710,1712,1715,1717,1719,1722,1724],{"class":215,"line":1157},[213,1711,1472],{"class":223},[213,1713,1714],{"class":308},"WriteByte",[213,1716,649],{"class":223},[213,1718,776],{"class":652},[213,1720,1721],{"class":232},"x",[213,1723,776],{"class":652},[213,1725,656],{"class":223},[213,1727,1728],{"class":215,"line":1163},[213,1729,661],{"class":223},[213,1731,1732,1734,1736,1738,1740],{"class":215,"line":1169},[213,1733,1491],{"class":223},[213,1735,728],{"class":219},[213,1737,1496],{"class":223},[213,1739,1499],{"class":308},[213,1741,1742],{"class":223},"()\n",[935,1744,1746,1747,676],{"id":1745},"конвертация-string-byte","Конвертация string ↔ ",[213,1748],{},[204,1750,1752],{"className":206,"code":1751,"language":208,"meta":209,"style":209},"s := \"hello\"\nb := []byte(s)  \u002F\u002F копирование\ns2 := string(b) \u002F\u002F копирование обратно\n",[52,1753,1754,1762,1778],{"__ignoreMap":209},[213,1755,1756,1758,1760],{"class":215,"line":216},[213,1757,948],{"class":223},[213,1759,288],{"class":219},[213,1761,1335],{"class":652},[213,1763,1764,1766,1768,1770,1772,1775],{"class":215,"line":236},[213,1765,493],{"class":223},[213,1767,288],{"class":219},[213,1769,1287],{"class":223},[213,1771,676],{"class":219},[213,1773,1774],{"class":223},"(s)  ",[213,1776,1777],{"class":261},"\u002F\u002F копирование\n",[213,1779,1780,1783,1785,1787,1790],{"class":215,"line":251},[213,1781,1782],{"class":223},"s2 ",[213,1784,288],{"class":219},[213,1786,1393],{"class":219},[213,1788,1789],{"class":223},"(b) ",[213,1791,1792],{"class":261},"\u002F\u002F копирование обратно\n",[11,1794,1795,1796,1798],{},"Оба преобразования — аллокация. Компилятор умеет избегать лишних копий в некоторых случаях (например, при ",[52,1797,1416],{}," в выражении сравнения), но рассчитывать на это не стоит.",[14,1800],{},[17,1802,1804],{"id":1803},"константы-и-iota","Константы и iota",[11,1806,1807],{},"Константы в Go существуют в двух формах. Нетипизированные константы обладают большей гибкостью: они хранятся с произвольной точностью и могут использоваться с любым совместимым типом. Типизированные константы жёстко привязаны к типу.",[204,1809,1811],{"className":206,"code":1810,"language":208,"meta":209,"style":209},"const Pi = 3.14159          \u002F\u002F нетипизированная — подойдёт и для float32, и для float64\nconst E float64 = 2.71828   \u002F\u002F типизированная — только float64\n\nvar x float32 = Pi  \u002F\u002F ок: нетипизированная константа подстраивается\nvar y float32 = E   \u002F\u002F ошибка: E уже типизирована как float64\n",[52,1812,1813,1829,1847,1851,1868],{"__ignoreMap":209},[213,1814,1815,1818,1821,1823,1826],{"class":215,"line":216},[213,1816,1817],{"class":219},"const",[213,1819,1820],{"class":232}," Pi",[213,1822,229],{"class":219},[213,1824,1825],{"class":232}," 3.14159",[213,1827,1828],{"class":261},"          \u002F\u002F нетипизированная — подойдёт и для float32, и для float64\n",[213,1830,1831,1833,1836,1839,1841,1844],{"class":215,"line":236},[213,1832,1817],{"class":219},[213,1834,1835],{"class":232}," E",[213,1837,1838],{"class":219}," float64",[213,1840,229],{"class":219},[213,1842,1843],{"class":232}," 2.71828",[213,1845,1846],{"class":261},"   \u002F\u002F типизированная — только float64\n",[213,1848,1849],{"class":215,"line":251},[213,1850,255],{"emptyLinePlaceholder":254},[213,1852,1853,1855,1858,1860,1862,1865],{"class":215,"line":258},[213,1854,220],{"class":219},[213,1856,1857],{"class":223}," x ",[213,1859,404],{"class":219},[213,1861,229],{"class":219},[213,1863,1864],{"class":223}," Pi  ",[213,1866,1867],{"class":261},"\u002F\u002F ок: нетипизированная константа подстраивается\n",[213,1869,1870,1872,1875,1877,1879,1882],{"class":215,"line":265},[213,1871,220],{"class":219},[213,1873,1874],{"class":223}," y ",[213,1876,404],{"class":219},[213,1878,229],{"class":219},[213,1880,1881],{"class":223}," E   ",[213,1883,1884],{"class":261},"\u002F\u002F ошибка: E уже типизирована как float64\n",[11,1886,1887,1892,1893,1895],{},[196,1888,1889],{},[52,1890,1891],{},"iota"," — встроенный счётчик в блоках ",[52,1894,1817],{},". Сбрасывается до 0 в каждом новом блоке и инкрементируется с каждой константой:",[204,1897,1899],{"className":206,"code":1898,"language":208,"meta":209,"style":209},"type Direction int\n\nconst (\n    North Direction = iota \u002F\u002F 0\n    East                   \u002F\u002F 1\n    South                  \u002F\u002F 2\n    West                   \u002F\u002F 3\n)\n\n\u002F\u002F iota можно использовать в выражениях\ntype ByteSize float64\n\nconst (\n    _           = iota             \u002F\u002F пропускаем 0 через blank identifier\n    KB ByteSize = 1 \u003C\u003C (10 * iota) \u002F\u002F 1 \u003C\u003C 10 = 1024\n    MB                             \u002F\u002F 1 \u003C\u003C 20\n    GB                             \u002F\u002F 1 \u003C\u003C 30\n    TB                             \u002F\u002F 1 \u003C\u003C 40\n)\n",[52,1900,1901,1911,1915,1922,1937,1945,1953,1961,1965,1969,1974,1984,1988,1994,2007,2037,2045,2053,2062],{"__ignoreMap":209},[213,1902,1903,1905,1908],{"class":215,"line":216},[213,1904,692],{"class":219},[213,1906,1907],{"class":308}," Direction",[213,1909,1910],{"class":219}," int\n",[213,1912,1913],{"class":215,"line":236},[213,1914,255],{"emptyLinePlaceholder":254},[213,1916,1917,1919],{"class":215,"line":251},[213,1918,1817],{"class":219},[213,1920,1921],{"class":223}," (\n",[213,1923,1924,1927,1929,1931,1934],{"class":215,"line":258},[213,1925,1926],{"class":232},"    North",[213,1928,1907],{"class":308},[213,1930,229],{"class":219},[213,1932,1933],{"class":232}," iota",[213,1935,1936],{"class":261}," \u002F\u002F 0\n",[213,1938,1939,1942],{"class":215,"line":265},[213,1940,1941],{"class":232},"    East",[213,1943,1944],{"class":261},"                   \u002F\u002F 1\n",[213,1946,1947,1950],{"class":215,"line":271},[213,1948,1949],{"class":232},"    South",[213,1951,1952],{"class":261},"                  \u002F\u002F 2\n",[213,1954,1955,1958],{"class":215,"line":276},[213,1956,1957],{"class":232},"    West",[213,1959,1960],{"class":261},"                   \u002F\u002F 3\n",[213,1962,1963],{"class":215,"line":282},[213,1964,656],{"class":223},[213,1966,1967],{"class":215,"line":302},[213,1968,255],{"emptyLinePlaceholder":254},[213,1970,1971],{"class":215,"line":1126},[213,1972,1973],{"class":261},"\u002F\u002F iota можно использовать в выражениях\n",[213,1975,1976,1978,1981],{"class":215,"line":1152},[213,1977,692],{"class":219},[213,1979,1980],{"class":308}," ByteSize",[213,1982,1983],{"class":219}," float64\n",[213,1985,1986],{"class":215,"line":1157},[213,1987,255],{"emptyLinePlaceholder":254},[213,1989,1990,1992],{"class":215,"line":1163},[213,1991,1817],{"class":219},[213,1993,1921],{"class":223},[213,1995,1996,1999,2002,2004],{"class":215,"line":1169},[213,1997,1998],{"class":232},"    _",[213,2000,2001],{"class":219},"           =",[213,2003,1933],{"class":232},[213,2005,2006],{"class":261},"             \u002F\u002F пропускаем 0 через blank identifier\n",[213,2008,2009,2012,2014,2016,2018,2021,2023,2026,2029,2031,2034],{"class":215,"line":1175},[213,2010,2011],{"class":232},"    KB",[213,2013,1980],{"class":308},[213,2015,229],{"class":219},[213,2017,560],{"class":232},[213,2019,2020],{"class":219}," \u003C\u003C",[213,2022,725],{"class":223},[213,2024,2025],{"class":232},"10",[213,2027,2028],{"class":219}," *",[213,2030,1933],{"class":232},[213,2032,2033],{"class":223},") ",[213,2035,2036],{"class":261},"\u002F\u002F 1 \u003C\u003C 10 = 1024\n",[213,2038,2039,2042],{"class":215,"line":1181},[213,2040,2041],{"class":232},"    MB",[213,2043,2044],{"class":261},"                             \u002F\u002F 1 \u003C\u003C 20\n",[213,2046,2047,2050],{"class":215,"line":1187},[213,2048,2049],{"class":232},"    GB",[213,2051,2052],{"class":261},"                             \u002F\u002F 1 \u003C\u003C 30\n",[213,2054,2056,2059],{"class":215,"line":2055},18,[213,2057,2058],{"class":232},"    TB",[213,2060,2061],{"class":261},"                             \u002F\u002F 1 \u003C\u003C 40\n",[213,2063,2065],{"class":215,"line":2064},19,[213,2066,656],{"class":223},[14,2068],{},[17,2070,2072],{"id":2071},"явное-приведение-типов","Явное приведение типов",[11,2074,2075,2076,2079,2080,188,2082,2084],{},"Все примеры выше используют явное приведение, и это не случайно — в Go ",[196,2077,2078],{},"нет неявных числовых преобразований вообще",". Даже ",[52,2081,154],{},[52,2083,93],{}," нельзя сложить без явного каста:",[204,2086,2088],{"className":206,"code":2087,"language":208,"meta":209,"style":209},"var i int = 42\nvar f float64 = float64(i)\nvar u uint = uint(f)\n",[52,2089,2090,2103,2118],{"__ignoreMap":209},[213,2091,2092,2094,2096,2098,2100],{"class":215,"line":216},[213,2093,220],{"class":219},[213,2095,346],{"class":223},[213,2097,154],{"class":219},[213,2099,229],{"class":219},[213,2101,2102],{"class":232}," 42\n",[213,2104,2105,2107,2109,2111,2113,2115],{"class":215,"line":236},[213,2106,220],{"class":219},[213,2108,358],{"class":223},[213,2110,361],{"class":219},[213,2112,229],{"class":219},[213,2114,1838],{"class":219},[213,2116,2117],{"class":223},"(i)\n",[213,2119,2120,2122,2125,2127,2129,2132],{"class":215,"line":251},[213,2121,220],{"class":219},[213,2123,2124],{"class":223}," u ",[213,2126,167],{"class":219},[213,2128,229],{"class":219},[213,2130,2131],{"class":219}," uint",[213,2133,2134],{"class":223},"(f)\n",[11,2136,2137],{},"При приведении к меньшему типу происходит усечение без паники:",[204,2139,2141],{"className":206,"code":2140,"language":208,"meta":209,"style":209},"var big int = 300\nvar small int8 = int8(big)\nfmt.Println(small) \u002F\u002F 44 — переполнение, Go не проверяет это в рантайме\n",[52,2142,2143,2157,2174],{"__ignoreMap":209},[213,2144,2145,2147,2150,2152,2154],{"class":215,"line":216},[213,2146,220],{"class":219},[213,2148,2149],{"class":223}," big ",[213,2151,154],{"class":219},[213,2153,229],{"class":219},[213,2155,2156],{"class":232}," 300\n",[213,2158,2159,2161,2164,2166,2168,2171],{"class":215,"line":236},[213,2160,220],{"class":219},[213,2162,2163],{"class":223}," small ",[213,2165,54],{"class":219},[213,2167,229],{"class":219},[213,2169,2170],{"class":219}," int8",[213,2172,2173],{"class":223},"(big)\n",[213,2175,2176,2178,2180,2183],{"class":215,"line":251},[213,2177,305],{"class":223},[213,2179,309],{"class":308},[213,2181,2182],{"class":223},"(small) ",[213,2184,2185],{"class":261},"\u002F\u002F 44 — переполнение, Go не проверяет это в рантайме\n",[11,2187,2188,2189,2192,2193,2195,2196,2199],{},"300 в двоичном виде: ",[52,2190,2191],{},"100101100",". В ",[52,2194,54],{}," помещаются только младшие 8 бит: ",[52,2197,2198],{},"00101100"," = 44. Старший бит у результата равен 0, поэтому знак остаётся положительным. Никаких паник, никаких ошибок — ответственность на разработчике.",[14,2201],{},[17,2203,2205],{"id":2204},"вопросы-на-собеседовании","Вопросы на собеседовании",[11,2207,2208,2217,2220,2221,2223,2224,2226],{},[196,2209,2210,2211,2213,2214,2216],{},"Q: Чем ",[52,2212,154],{}," отличается от ",[52,2215,93],{},"?",[2218,2219],"br",{},"\nA: ",[52,2222,154],{}," — платформозависимый тип (32 или 64 бита в зависимости от архитектуры), ",[52,2225,93],{}," — всегда 64 бита. Это разные типы: компилятор не позволит их смешать без явного приведения. На 64-битной системе они одного размера, но всё равно не совместимы.",[11,2228,2229,2232,2234,2235,2237,2238,2240,2241,2243,2244,2240,2246,2243,2249,2240,2251,2243,2253,2240,2255,2258,2259,2262],{},[196,2230,2231],{},"Q: Что такое zero value? Приведите примеры.",[2218,2233],{},"\nA: Значение по умолчанию, которое Go присваивает переменной при объявлении через ",[52,2236,220],{}," без инициализации. ",[52,2239,154],{}," → ",[52,2242,1237],{},", ",[52,2245,361],{},[52,2247,2248],{},"0.0",[52,2250,373],{},[52,2252,594],{},[52,2254,386],{},[52,2256,2257],{},"\"\"",", указатели, слайсы, каналы, функции → ",[52,2260,2261],{},"nil",". Это гарантирует отсутствие \"мусора\" в памяти и убирает целый класс ошибок.",[11,2264,2265,2272,2274,2275,2277,2278,473],{},[196,2266,2267,2268,2271],{},"Q: Почему ",[52,2269,2270],{},"0.1 + 0.2 != 0.3"," в Go?",[2218,2273],{},"\nA: Числа с плавающей точкой хранятся в формате IEEE 754. Большинство десятичных дробей не имеют точного двоичного представления — ",[52,2276,578],{}," в двоичном виде это бесконечная дробь. При арифметике накапливается ошибка округления. Это не баг Go — одно и то же поведение в Python, Java, C. Правильный способ сравнения: ",[52,2279,2280],{},"math.Abs(a-b) \u003C epsilon",[11,2282,2283,2289,2220,2291,2293,2294,2297,2298,2301,2302,473],{},[196,2284,2267,2285,2288],{},[52,2286,2287],{},"len(\"Привет\")"," возвращает 12, а не 6?",[2218,2290],{},[52,2292,920],{}," возвращает длину строки в ",[196,2295,2296],{},"байтах",", не в символах. \"Привет\" в UTF-8 — 6 кириллических символов по 2 байта = 12 байт. Для подсчёта символов используют ",[52,2299,2300],{},"utf8.RuneCountInString(s)"," или ",[52,2303,2304],{},"len([]rune(s))",[11,2306,2307,2317,2319,2320,2322,2323,2325,2326,473],{},[196,2308,2309,2310,2313,2314,2216],{},"Q: Что вернёт ",[52,2311,2312],{},"s[0]"," для строки ",[52,2315,2316],{},"s := \"Привет\"",[2218,2318],{},"\nA: Тип ",[52,2321,676],{}," (uint8) со значением 208 — это первый байт двухбайтной UTF-8 кодировки символа 'П'. Не сам символ 'П'. Чтобы получить символ, нужно итерироваться через ",[52,2324,1200],{}," или конвертировать в ",[52,2327,2328],{},"[]rune",[11,2330,2331,2336,2220,2338,2341,2342,2344,2345,2347,2348,2351],{},[196,2332,2210,2333,2335],{},[52,2334,1200],{}," по строке отличается от итерации через индекс?",[2218,2337],{},[52,2339,2340],{},"for i := range s"," декодирует UTF-8 и возвращает руны (",[52,2343,679],{},"), а ",[52,2346,1196],{}," — байтовая позиция начала руны. ",[52,2349,2350],{},"for i := 0; i \u003C len(s); i++"," итерируется по байтам — для многобайтных символов это даёт \"сломанные\" куски символов.",[11,2353,2354,2357,2359,2360,2362,2363,2366],{},[196,2355,2356],{},"Q: Можно ли изменить строку в Go? Почему?",[2218,2358],{},"\nA: Нет. Строки неизменяемы — ",[52,2361,932],{}," в StringHeader указывает на readonly память. Это позволяет безопасно передавать строки между горутинами без копирования и синхронизации. Для изменения нужно конвертировать в ",[52,2364,2365],{},"[]byte",", изменить, конвертировать обратно — каждый шаг это аллокация.",[11,2368,2369,2375,2377,2378,2381,2382,2384,2385,473],{},[196,2370,2371,2372,2374],{},"Q: Почему конкатенация строк в цикле через ",[52,2373,293],{}," — это плохо?",[2218,2376],{},"\nA: При каждом ",[52,2379,2380],{},"s += x"," создаётся новый строковый объект: выделяется память под новую строку, данные копируются. В цикле на 1000 итераций — 1000 аллокаций. Правильный способ — ",[52,2383,1423],{},", который аккумулирует данные и делает одну аллокацию в конце при вызове ",[52,2386,2387],{},"String()",[11,2389,2390,2393,2395,2396,2399,2400,2403],{},[196,2391,2392],{},"Q: Дорого ли передавать строку в функцию?",[2218,2394],{},"\nA: Нет. При передаче строки копируется только заголовок ",[52,2397,2398],{},"StringHeader"," — 16 байт (указатель + длина). Сами данные не копируются. Поэтому передавать строки по указателю (",[52,2401,2402],{},"*string",") не нужно и является антипаттерном.",[11,2405,2406,2412,2220,2414,2416,2417,2419,2420,2416,2422,2424,2425,473],{},[196,2407,2210,2408,2213,2410,2216],{},[52,2409,676],{},[52,2411,679],{},[2218,2413],{},[52,2415,676],{}," — псевдоним ",[52,2418,106],{},", один байт. ",[52,2421,679],{},[52,2423,80],{},", один Unicode code point. Один символ может состоять из нескольких байт: латиница — 1 байт, кириллица — 2, некоторые иероглифы — 3, эмодзи — 4. Если работаете с \"символами\" в человеческом понимании — используйте ",[52,2426,679],{},[11,2428,2429,2432,2434,2435,2438,2439,2301,2441,2443,2444,2447],{},[196,2430,2431],{},"Q: Что такое нетипизированная константа? Чем она отличается от типизированной?",[2218,2433],{},"\nA: Нетипизированная константа (",[52,2436,2437],{},"const Pi = 3.14",") хранится с произвольной точностью и может использоваться с любым совместимым типом — ",[52,2440,404],{},[52,2442,361],{},". Типизированная (",[52,2445,2446],{},"const E float64 = 2.71",") жёстко привязана к типу и не будет неявно конвертирована.",[11,2449,2450,2456,2458,2459,2461,2462,2464,2465,2467],{},[196,2451,2452,2453,2216],{},"Q: Что произойдёт при ",[52,2454,2455],{},"int8(300)",[2218,2457],{},"\nA: Переполнение без паники. 300 в двоичном виде — ",[52,2460,2191],{},", в ",[52,2463,54],{}," помещается только 8 младших бит — ",[52,2466,2198],{}," = 44. Так как старший бит результата 0, число остаётся положительным. Go не проверяет переполнение при явном приведении в рантайме. Переполнение при приведении — ответственность разработчика.",[14,2469],{},[2471,2472,2474],"h1",{"id":2473},"задачи-скалярные-типы","Задачи: Скалярные типы",[14,2476],{},[11,2478,2479],{},[196,2480,2481],{},"Задача 1: Границы типа",[11,2483,2484,2487],{},[196,2485,2486],{},"Уровень:"," Лёгкая",[11,2489,2490,2493],{},[196,2491,2492],{},"Что проверяет:"," понимание переполнения при приведении типов",[11,2495,2496,2499],{},[196,2497,2498],{},"Условие:"," Что выведет следующий код? Объясни почему.",[204,2501,2503],{"className":206,"code":2502,"language":208,"meta":209,"style":209},"package main\n\nimport \"fmt\"\n\nfunc main() {\n    var a int32 = 2147483647\n    a++\n    fmt.Println(a)\n\n    var b uint8 = 0\n    b--\n    fmt.Println(b)\n\n    var c int = 300\n    d := int8(c)\n    fmt.Println(d)\n}\n",[52,2504,2505,2513,2517,2530,2534,2544,2558,2566,2575,2579,2592,2600,2608,2612,2625,2637,2646],{"__ignoreMap":209},[213,2506,2507,2510],{"class":215,"line":216},[213,2508,2509],{"class":219},"package",[213,2511,2512],{"class":308}," main\n",[213,2514,2515],{"class":215,"line":236},[213,2516,255],{"emptyLinePlaceholder":254},[213,2518,2519,2522,2524,2527],{"class":215,"line":251},[213,2520,2521],{"class":219},"import",[213,2523,1089],{"class":652},[213,2525,2526],{"class":308},"fmt",[213,2528,2529],{"class":652},"\"\n",[213,2531,2532],{"class":215,"line":258},[213,2533,255],{"emptyLinePlaceholder":254},[213,2535,2536,2538,2541],{"class":215,"line":265},[213,2537,1519],{"class":219},[213,2539,2540],{"class":308}," main",[213,2542,2543],{"class":223},"() {\n",[213,2545,2546,2549,2551,2553,2555],{"class":215,"line":271},[213,2547,2548],{"class":219},"    var",[213,2550,224],{"class":223},[213,2552,80],{"class":219},[213,2554,229],{"class":219},[213,2556,2557],{"class":232}," 2147483647\n",[213,2559,2560,2563],{"class":215,"line":276},[213,2561,2562],{"class":223},"    a",[213,2564,2565],{"class":219},"++\n",[213,2567,2568,2570,2572],{"class":215,"line":282},[213,2569,644],{"class":223},[213,2571,309],{"class":308},[213,2573,2574],{"class":223},"(a)\n",[213,2576,2577],{"class":215,"line":302},[213,2578,255],{"emptyLinePlaceholder":254},[213,2580,2581,2583,2585,2587,2589],{"class":215,"line":1126},[213,2582,2548],{"class":219},[213,2584,241],{"class":223},[213,2586,106],{"class":219},[213,2588,229],{"class":219},[213,2590,2591],{"class":232}," 0\n",[213,2593,2594,2597],{"class":215,"line":1152},[213,2595,2596],{"class":223},"    b",[213,2598,2599],{"class":219},"--\n",[213,2601,2602,2604,2606],{"class":215,"line":1157},[213,2603,644],{"class":223},[213,2605,309],{"class":308},[213,2607,299],{"class":223},[213,2609,2610],{"class":215,"line":1163},[213,2611,255],{"emptyLinePlaceholder":254},[213,2613,2614,2616,2619,2621,2623],{"class":215,"line":1169},[213,2615,2548],{"class":219},[213,2617,2618],{"class":223}," c ",[213,2620,154],{"class":219},[213,2622,229],{"class":219},[213,2624,2156],{"class":232},[213,2626,2627,2630,2632,2634],{"class":215,"line":1175},[213,2628,2629],{"class":223},"    d ",[213,2631,288],{"class":219},[213,2633,2170],{"class":219},[213,2635,2636],{"class":223},"(c)\n",[213,2638,2639,2641,2643],{"class":215,"line":1181},[213,2640,644],{"class":223},[213,2642,309],{"class":308},[213,2644,2645],{"class":223},"(d)\n",[213,2647,2648],{"class":215,"line":1187},[213,2649,661],{"class":223},[11,2651,2652],{},[196,2653,2654],{},"Ожидаемый ответ:",[204,2656,2661],{"className":2657,"code":2659,"language":2660},[2658],"language-text","-2147483648\n255\n44\n","text",[52,2662,2659],{"__ignoreMap":209},[11,2664,2665],{},[196,2666,2667],{},"Решение:",[204,2669,2671],{"className":206,"code":2670,"language":208,"meta":209,"style":209},"\u002F\u002F a: int32 максимум = 2147483647 (2^31 - 1).\n\u002F\u002F При инкременте происходит переполнение —\n\u002F\u002F старший бит становится 1 (знаковый), результат -2147483648.\n\n\u002F\u002F b: uint8 минимум = 0. Декремент беззнакового 0\n\u002F\u002F оборачивается до максимума: 255 (2^8 - 1).\n\n\u002F\u002F c: 300 в двоичном виде = 100101100.\n\u002F\u002F int8 хранит только 8 бит: 00101100 = 44.\n\u002F\u002F Go не проверяет переполнение при явном приведении.\n",[52,2672,2673,2678,2683,2688,2692,2697,2702,2706,2711,2716],{"__ignoreMap":209},[213,2674,2675],{"class":215,"line":216},[213,2676,2677],{"class":261},"\u002F\u002F a: int32 максимум = 2147483647 (2^31 - 1).\n",[213,2679,2680],{"class":215,"line":236},[213,2681,2682],{"class":261},"\u002F\u002F При инкременте происходит переполнение —\n",[213,2684,2685],{"class":215,"line":251},[213,2686,2687],{"class":261},"\u002F\u002F старший бит становится 1 (знаковый), результат -2147483648.\n",[213,2689,2690],{"class":215,"line":258},[213,2691,255],{"emptyLinePlaceholder":254},[213,2693,2694],{"class":215,"line":265},[213,2695,2696],{"class":261},"\u002F\u002F b: uint8 минимум = 0. Декремент беззнакового 0\n",[213,2698,2699],{"class":215,"line":271},[213,2700,2701],{"class":261},"\u002F\u002F оборачивается до максимума: 255 (2^8 - 1).\n",[213,2703,2704],{"class":215,"line":276},[213,2705,255],{"emptyLinePlaceholder":254},[213,2707,2708],{"class":215,"line":282},[213,2709,2710],{"class":261},"\u002F\u002F c: 300 в двоичном виде = 100101100.\n",[213,2712,2713],{"class":215,"line":302},[213,2714,2715],{"class":261},"\u002F\u002F int8 хранит только 8 бит: 00101100 = 44.\n",[213,2717,2718],{"class":215,"line":1126},[213,2719,2720],{"class":261},"\u002F\u002F Go не проверяет переполнение при явном приведении.\n",[14,2722],{},[11,2724,2725],{},[196,2726,2727],{},"Задача 2: Сравнение float",[11,2729,2730,2732],{},[196,2731,2486],{}," Средняя",[11,2734,2735,2737],{},[196,2736,2492],{}," понимание IEEE 754 и правильного сравнения вещественных чисел",[11,2739,2740,2742,2743,2746,2747,2749,2750,2753,2754,2756],{},[196,2741,2498],{}," Напиши функцию ",[52,2744,2745],{},"equal(a, b float64) bool"," которая корректно сравнивает два числа с плавающей точкой. Функция должна возвращать ",[52,2748,591],{}," если числа равны с точностью до ",[52,2751,2752],{},"1e-9",". Также объясни почему стандартный ",[52,2755,472],{}," не работает для float.",[11,2758,2759],{},[196,2760,2761],{},"Примеры:",[204,2763,2766],{"className":2764,"code":2765,"language":2660},[2658],"equal(0.1+0.2, 0.3)    → true\nequal(1.0, 1.0)        → true\nequal(1.0, 1.000000001) → false\nequal(1.0, 1.0000000001) → true (разница меньше 1e-9)\n",[52,2767,2765],{"__ignoreMap":209},[11,2769,2770],{},[196,2771,2667],{},[204,2773,2775],{"className":206,"code":2774,"language":208,"meta":209,"style":209},"package main\n\nimport (\n    \"fmt\"\n    \"math\"\n)\n\nfunc equal(a, b float64) bool {\n    return math.Abs(a-b) \u003C 1e-9\n}\n\nfunc main() {\n    fmt.Println(equal(0.1+0.2, 0.3))         \u002F\u002F true\n    fmt.Println(equal(1.0, 1.0))             \u002F\u002F true\n    fmt.Println(equal(1.0, 1.000000001))     \u002F\u002F false\n    fmt.Println(equal(1.0, 1.0000000001))    \u002F\u002F true\n}\n\n\u002F\u002F Почему == не работает:\n\u002F\u002F 0.1 в двоичной системе — бесконечная дробь.\n\u002F\u002F После арифметических операций накапливается ошибка представления.\n\u002F\u002F 0.1 + 0.2 в IEEE 754 = 0.30000000000000004, а не 0.3.\n\u002F\u002F Поэтому 0.1+0.2 == 0.3 → false.\n",[52,2776,2777,2783,2787,2793,2802,2811,2815,2819,2844,2870,2874,2878,2886,2917,2941,2966,2990,2994,2998,3003,3009,3015,3021],{"__ignoreMap":209},[213,2778,2779,2781],{"class":215,"line":216},[213,2780,2509],{"class":219},[213,2782,2512],{"class":308},[213,2784,2785],{"class":215,"line":236},[213,2786,255],{"emptyLinePlaceholder":254},[213,2788,2789,2791],{"class":215,"line":251},[213,2790,2521],{"class":219},[213,2792,1921],{"class":223},[213,2794,2795,2798,2800],{"class":215,"line":258},[213,2796,2797],{"class":652},"    \"",[213,2799,2526],{"class":308},[213,2801,2529],{"class":652},[213,2803,2804,2806,2809],{"class":215,"line":265},[213,2805,2797],{"class":652},[213,2807,2808],{"class":308},"math",[213,2810,2529],{"class":652},[213,2812,2813],{"class":215,"line":271},[213,2814,656],{"class":223},[213,2816,2817],{"class":215,"line":276},[213,2818,255],{"emptyLinePlaceholder":254},[213,2820,2821,2823,2826,2828,2831,2833,2836,2838,2840,2842],{"class":215,"line":282},[213,2822,1519],{"class":219},[213,2824,2825],{"class":308}," equal",[213,2827,649],{"class":223},[213,2829,2830],{"class":1527},"a",[213,2832,2243],{"class":223},[213,2834,2835],{"class":1527},"b",[213,2837,1838],{"class":219},[213,2839,2033],{"class":223},[213,2841,373],{"class":219},[213,2843,890],{"class":223},[213,2845,2846,2849,2852,2854,2856,2858,2861,2863,2865,2867],{"class":215,"line":302},[213,2847,2848],{"class":219},"    return",[213,2850,2851],{"class":223}," math.",[213,2853,540],{"class":308},[213,2855,516],{"class":223},[213,2857,551],{"class":219},[213,2859,2860],{"class":223},"b) ",[213,2862,557],{"class":219},[213,2864,560],{"class":232},[213,2866,563],{"class":219},[213,2868,2869],{"class":232},"9\n",[213,2871,2872],{"class":215,"line":1126},[213,2873,661],{"class":223},[213,2875,2876],{"class":215,"line":1152},[213,2877,255],{"emptyLinePlaceholder":254},[213,2879,2880,2882,2884],{"class":215,"line":1157},[213,2881,1519],{"class":219},[213,2883,2540],{"class":308},[213,2885,2543],{"class":223},[213,2887,2888,2890,2892,2894,2897,2899,2901,2903,2906,2908,2911,2914],{"class":215,"line":1163},[213,2889,644],{"class":223},[213,2891,309],{"class":308},[213,2893,649],{"class":223},[213,2895,2896],{"class":308},"equal",[213,2898,649],{"class":223},[213,2900,578],{"class":232},[213,2902,293],{"class":219},[213,2904,2905],{"class":232},"0.2",[213,2907,2243],{"class":223},[213,2909,2910],{"class":232},"0.3",[213,2912,2913],{"class":223},"))         ",[213,2915,2916],{"class":261},"\u002F\u002F true\n",[213,2918,2919,2921,2923,2925,2927,2929,2932,2934,2936,2939],{"class":215,"line":1169},[213,2920,644],{"class":223},[213,2922,309],{"class":308},[213,2924,649],{"class":223},[213,2926,2896],{"class":308},[213,2928,649],{"class":223},[213,2930,2931],{"class":232},"1.0",[213,2933,2243],{"class":223},[213,2935,2931],{"class":232},[213,2937,2938],{"class":223},"))             ",[213,2940,2916],{"class":261},[213,2942,2943,2945,2947,2949,2951,2953,2955,2957,2960,2963],{"class":215,"line":1175},[213,2944,644],{"class":223},[213,2946,309],{"class":308},[213,2948,649],{"class":223},[213,2950,2896],{"class":308},[213,2952,649],{"class":223},[213,2954,2931],{"class":232},[213,2956,2243],{"class":223},[213,2958,2959],{"class":232},"1.000000001",[213,2961,2962],{"class":223},"))     ",[213,2964,2965],{"class":261},"\u002F\u002F false\n",[213,2967,2968,2970,2972,2974,2976,2978,2980,2982,2985,2988],{"class":215,"line":1181},[213,2969,644],{"class":223},[213,2971,309],{"class":308},[213,2973,649],{"class":223},[213,2975,2896],{"class":308},[213,2977,649],{"class":223},[213,2979,2931],{"class":232},[213,2981,2243],{"class":223},[213,2983,2984],{"class":232},"1.0000000001",[213,2986,2987],{"class":223},"))    ",[213,2989,2916],{"class":261},[213,2991,2992],{"class":215,"line":1187},[213,2993,661],{"class":223},[213,2995,2996],{"class":215,"line":2055},[213,2997,255],{"emptyLinePlaceholder":254},[213,2999,3000],{"class":215,"line":2064},[213,3001,3002],{"class":261},"\u002F\u002F Почему == не работает:\n",[213,3004,3006],{"class":215,"line":3005},20,[213,3007,3008],{"class":261},"\u002F\u002F 0.1 в двоичной системе — бесконечная дробь.\n",[213,3010,3012],{"class":215,"line":3011},21,[213,3013,3014],{"class":261},"\u002F\u002F После арифметических операций накапливается ошибка представления.\n",[213,3016,3018],{"class":215,"line":3017},22,[213,3019,3020],{"class":261},"\u002F\u002F 0.1 + 0.2 в IEEE 754 = 0.30000000000000004, а не 0.3.\n",[213,3022,3024],{"class":215,"line":3023},23,[213,3025,3026],{"class":261},"\u002F\u002F Поэтому 0.1+0.2 == 0.3 → false.\n",[14,3028],{},[11,3030,3031],{},[196,3032,3033],{},"Задача 3: Подсчёт байт и рун",[11,3035,3036,3038],{},[196,3037,2486],{}," Сложная",[11,3040,3041,3043],{},[196,3042,2492],{}," глубокое понимание string, byte, rune и UTF-8",[11,3045,3046,2742,3048,3051],{},[196,3047,2498],{},[52,3049,3050],{},"analyzeString(s string)"," которая выводит:",[740,3053,3054,3057,3060,3063],{},[743,3055,3056],{},"Длину строки в байтах",[743,3058,3059],{},"Длину строки в символах (рунах)",[743,3061,3062],{},"Каждый символ с его байтовой позицией, рунным значением и количеством байт которые он занимает",[743,3064,3065],{},"Является ли строка валидным UTF-8",[11,3067,3068],{},[196,3069,2761],{},[204,3071,3074],{"className":3072,"code":3073,"language":2660},[2658],"analyzeString(\"Hi!\")\n→ Байт: 3, Символов: 3\n→ [0] 'H' rune=72  bytes=1\n→ [1] 'i' rune=105 bytes=1\n→ [2] '!' rune=33  bytes=1\n→ Валидный UTF-8: true\n\nanalyzeString(\"Го!\")\n→ Байт: 5, Символов: 3\n→ [0] 'Г' rune=1043 bytes=2\n→ [2] 'о' rune=1086 bytes=2\n→ [4] '!' rune=33   bytes=1\n→ Валидный UTF-8: true\n",[52,3075,3073],{"__ignoreMap":209},[11,3077,3078,3081,3082,3085,3086,473],{},[196,3079,3080],{},"Подсказка:"," Для определения размера руны используй ",[52,3083,3084],{},"utf8.RuneLen(r)",". Для валидации — ",[52,3087,3088],{},"utf8.ValidString(s)",[11,3090,3091],{},[196,3092,2667],{},[204,3094,3096],{"className":206,"code":3095,"language":208,"meta":209,"style":209},"package main\n\nimport (\n    \"fmt\"\n    \"unicode\u002Futf8\"\n)\n\nfunc analyzeString(s string) {\n    fmt.Printf(\"Байт: %d, Символов: %d\\n\", len(s), utf8.RuneCountInString(s))\n\n    for i, r := range s {\n        size := utf8.RuneLen(r)\n        fmt.Printf(\"[%d] '%c' rune=%-6d bytes=%d\\n\", i, r, r, size)\n    }\n\n    fmt.Printf(\"Валидный UTF-8: %v\\n\", utf8.ValidString(s))\n}\n\nfunc main() {\n    analyzeString(\"Hi!\")\n    analyzeString(\"Го!\")\n    analyzeString(\"Hello, 世界\")\n}\n\n\u002F\u002F Ключевые моменты:\n\u002F\u002F - range по строке возвращает байтовую позицию и руну (не индекс символа)\n\u002F\u002F - len() считает байты, utf8.RuneCountInString() считает символы\n\u002F\u002F - кириллица занимает 2 байта, некоторые иероглифы — 3\n",[52,3097,3098,3104,3108,3114,3122,3131,3135,3139,3154,3187,3191,3204,3220,3256,3261,3265,3289,3293,3297,3305,3317,3328,3339,3343,3348,3354,3360,3366],{"__ignoreMap":209},[213,3099,3100,3102],{"class":215,"line":216},[213,3101,2509],{"class":219},[213,3103,2512],{"class":308},[213,3105,3106],{"class":215,"line":236},[213,3107,255],{"emptyLinePlaceholder":254},[213,3109,3110,3112],{"class":215,"line":251},[213,3111,2521],{"class":219},[213,3113,1921],{"class":223},[213,3115,3116,3118,3120],{"class":215,"line":258},[213,3117,2797],{"class":652},[213,3119,2526],{"class":308},[213,3121,2529],{"class":652},[213,3123,3124,3126,3129],{"class":215,"line":265},[213,3125,2797],{"class":652},[213,3127,3128],{"class":308},"unicode\u002Futf8",[213,3130,2529],{"class":652},[213,3132,3133],{"class":215,"line":271},[213,3134,656],{"class":223},[213,3136,3137],{"class":215,"line":276},[213,3138,255],{"emptyLinePlaceholder":254},[213,3140,3141,3143,3146,3148,3150,3152],{"class":215,"line":282},[213,3142,1519],{"class":219},[213,3144,3145],{"class":308}," analyzeString",[213,3147,649],{"class":223},[213,3149,1528],{"class":1527},[213,3151,1393],{"class":219},[213,3153,1533],{"class":223},[213,3155,3156,3158,3160,3162,3165,3167,3170,3173,3175,3177,3179,3182,3184],{"class":215,"line":302},[213,3157,644],{"class":223},[213,3159,811],{"class":308},[213,3161,649],{"class":223},[213,3163,3164],{"class":652},"\"Байт: ",[213,3166,1138],{"class":232},[213,3168,3169],{"class":652},", Символов: ",[213,3171,3172],{"class":232},"%d\\n",[213,3174,816],{"class":652},[213,3176,2243],{"class":223},[213,3178,968],{"class":308},[213,3180,3181],{"class":223},"(s), utf8.",[213,3183,986],{"class":308},[213,3185,3186],{"class":223},"(s))\n",[213,3188,3189],{"class":215,"line":1126},[213,3190,255],{"emptyLinePlaceholder":254},[213,3192,3193,3196,3198,3200,3202],{"class":215,"line":1152},[213,3194,3195],{"class":219},"    for",[213,3197,1115],{"class":223},[213,3199,288],{"class":219},[213,3201,1120],{"class":219},[213,3203,1123],{"class":223},[213,3205,3206,3209,3211,3214,3217],{"class":215,"line":1157},[213,3207,3208],{"class":223},"        size ",[213,3210,288],{"class":219},[213,3212,3213],{"class":223}," utf8.",[213,3215,3216],{"class":308},"RuneLen",[213,3218,3219],{"class":223},"(r)\n",[213,3221,3222,3225,3227,3229,3232,3234,3237,3240,3243,3246,3249,3251,3253],{"class":215,"line":1163},[213,3223,3224],{"class":223},"        fmt.",[213,3226,811],{"class":308},[213,3228,649],{"class":223},[213,3230,3231],{"class":652},"\"[",[213,3233,1138],{"class":232},[213,3235,3236],{"class":652},"] '",[213,3238,3239],{"class":232},"%c",[213,3241,3242],{"class":652},"' rune=",[213,3244,3245],{"class":232},"%-6d",[213,3247,3248],{"class":652}," bytes=",[213,3250,3172],{"class":232},[213,3252,816],{"class":652},[213,3254,3255],{"class":223},", i, r, r, size)\n",[213,3257,3258],{"class":215,"line":1169},[213,3259,3260],{"class":223},"    }\n",[213,3262,3263],{"class":215,"line":1175},[213,3264,255],{"emptyLinePlaceholder":254},[213,3266,3267,3269,3271,3273,3276,3279,3281,3284,3287],{"class":215,"line":1181},[213,3268,644],{"class":223},[213,3270,811],{"class":308},[213,3272,649],{"class":223},[213,3274,3275],{"class":652},"\"Валидный UTF-8: ",[213,3277,3278],{"class":232},"%v\\n",[213,3280,816],{"class":652},[213,3282,3283],{"class":223},", utf8.",[213,3285,3286],{"class":308},"ValidString",[213,3288,3186],{"class":223},[213,3290,3291],{"class":215,"line":1187},[213,3292,661],{"class":223},[213,3294,3295],{"class":215,"line":2055},[213,3296,255],{"emptyLinePlaceholder":254},[213,3298,3299,3301,3303],{"class":215,"line":2064},[213,3300,1519],{"class":219},[213,3302,2540],{"class":308},[213,3304,2543],{"class":223},[213,3306,3307,3310,3312,3315],{"class":215,"line":3005},[213,3308,3309],{"class":308},"    analyzeString",[213,3311,649],{"class":223},[213,3313,3314],{"class":652},"\"Hi!\"",[213,3316,656],{"class":223},[213,3318,3319,3321,3323,3326],{"class":215,"line":3011},[213,3320,3309],{"class":308},[213,3322,649],{"class":223},[213,3324,3325],{"class":652},"\"Го!\"",[213,3327,656],{"class":223},[213,3329,3330,3332,3334,3337],{"class":215,"line":3017},[213,3331,3309],{"class":308},[213,3333,649],{"class":223},[213,3335,3336],{"class":652},"\"Hello, 世界\"",[213,3338,656],{"class":223},[213,3340,3341],{"class":215,"line":3023},[213,3342,661],{"class":223},[213,3344,3346],{"class":215,"line":3345},24,[213,3347,255],{"emptyLinePlaceholder":254},[213,3349,3351],{"class":215,"line":3350},25,[213,3352,3353],{"class":261},"\u002F\u002F Ключевые моменты:\n",[213,3355,3357],{"class":215,"line":3356},26,[213,3358,3359],{"class":261},"\u002F\u002F - range по строке возвращает байтовую позицию и руну (не индекс символа)\n",[213,3361,3363],{"class":215,"line":3362},27,[213,3364,3365],{"class":261},"\u002F\u002F - len() считает байты, utf8.RuneCountInString() считает символы\n",[213,3367,3369],{"class":215,"line":3368},28,[213,3370,3371],{"class":261},"\u002F\u002F - кириллица занимает 2 байта, некоторые иероглифы — 3\n",[14,3373],{},[17,3375,3377],{"id":3376},"практика","Практика",[3379,3380,3383,3392,3408],"quiz",{"answer":3381,"id":3382,"xp":2025},"3","scalar-q1",[11,3384,3385,3386,3389,3390,2216],{},"Какой будет результат выражения ",[52,3387,3388],{},"7 \u002F 2"," в Go, если обе переменные типа ",[52,3391,154],{},[3393,3394,3395],"template",{"v-slot:options":209},[740,3396,3397,3400,3403,3405],{},[743,3398,3399],{},"3.5",[743,3401,3402],{},"4",[743,3404,3381],{},[743,3406,3407],{},"Ошибка компиляции",[3393,3409,3410],{"v-slot:explanation":209},[11,3411,3412,3413,3416,3417,473],{},"При целочисленном делении в Go дробная часть отбрасывается. ",[52,3414,3415],{},"7 \u002F 2 = 3"," (не 3.5). Для получения 3.5 нужно использовать ",[52,3418,361],{},[3420,3421,3424,3475],"predict",{"answer":3402,"id":3422,"xp":3423},"scalar-p1","15",[3393,3425,3426],{"v-slot:code":209},[204,3427,3429],{"className":206,"code":3428,"language":208,"meta":209,"style":209},"x := 10\ny := 3\nfmt.Println(x % y + x\u002Fy)\n",[52,3430,3431,3440,3450],{"__ignoreMap":209},[213,3432,3433,3436,3438],{"class":215,"line":216},[213,3434,3435],{"class":223},"x ",[213,3437,288],{"class":219},[213,3439,233],{"class":232},[213,3441,3442,3445,3447],{"class":215,"line":236},[213,3443,3444],{"class":223},"y ",[213,3446,288],{"class":219},[213,3448,3449],{"class":232}," 3\n",[213,3451,3452,3454,3456,3459,3462,3464,3466,3469,3472],{"class":215,"line":251},[213,3453,305],{"class":223},[213,3455,309],{"class":308},[213,3457,3458],{"class":223},"(x ",[213,3460,3461],{"class":219},"%",[213,3463,1874],{"class":223},[213,3465,293],{"class":219},[213,3467,3468],{"class":223}," x",[213,3470,3471],{"class":219},"\u002F",[213,3473,3474],{"class":223},"y)\n",[3393,3476,3477],{"v-slot:hint":209},[11,3478,3479,3481,3482,2243,3485,3488,3489],{},[52,3480,3461],{}," — остаток от деления. ",[52,3483,3484],{},"10 % 3 = 1",[52,3486,3487],{},"10 \u002F 3 = 3"," (целочисленное). ",[52,3490,3491],{},"1 + 3 = ?",[3493,3494,3498,3512,3523],"code-task",{"expected":3495,"id":3496,"xp":3497},"Привет, Go!","scalar-ct1","20",[11,3499,3500,3501,3504,3505,3507,3508,3511],{},"Объявите переменную ",[52,3502,3503],{},"msg"," типа ",[52,3506,386],{}," со значением ",[52,3509,3510],{},"\"Привет, Go!\""," и выведите её.",[3393,3513,3514],{"v-slot:template":209},[204,3515,3517],{"className":206,"code":3516,"language":208,"meta":209,"style":209},"\u002F\u002F Объявите переменную msg и выведите её\n",[52,3518,3519],{"__ignoreMap":209},[213,3520,3521],{"class":215,"line":216},[213,3522,3516],{"class":261},[3393,3524,3525],{"v-slot:hints":209},[740,3526,3527,3536],{},[743,3528,3529,3530,3533,3534],{},"Используйте ",[52,3531,3532],{},"var msg string = \"...\""," или короткую форму ",[52,3535,288],{},[743,3537,3538,3539],{},"Для вывода: ",[52,3540,3541],{},"fmt.Println(msg)",[3543,3544,3545],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":209,"searchDepth":236,"depth":236,"links":3547},[3548,3549,3550,3551,3552,3553,3564,3565,3566,3567],{"id":19,"depth":236,"text":20},{"id":323,"depth":236,"text":324},{"id":397,"depth":236,"text":398},{"id":373,"depth":236,"text":373},{"id":669,"depth":236,"text":670},{"id":863,"depth":236,"text":864,"children":3554},[3555,3556,3557,3558,3559,3560,3562],{"id":937,"depth":251,"text":938},{"id":1022,"depth":251,"text":1023},{"id":1211,"depth":251,"text":1212},{"id":1320,"depth":251,"text":1321},{"id":1508,"depth":251,"text":1509},{"id":1574,"depth":251,"text":3561},"Конкатенация оператором +",{"id":1745,"depth":251,"text":3563},"Конвертация string ↔ byte",{"id":1803,"depth":236,"text":1804},{"id":2071,"depth":236,"text":2072},{"id":2204,"depth":236,"text":2205},{"id":3376,"depth":236,"text":3377},1781458308738]