[{"data":1,"prerenderedAt":4774},["ShallowReactive",2],{"content-\u002F01-basics\u002F04-structs":3},{"id":4,"title":5,"body":6,"description":12,"difficulty":4759,"extension":4760,"meta":4761,"module":4762,"navigation":97,"next":4763,"order":71,"path":4764,"prev":2096,"seo":4765,"slug":4766,"stem":4767,"tags":4768,"__hash__":4773},"content\u002F01-basics\u002F04-structs\u002Findex.md","Структуры в Go",{"type":7,"value":8,"toc":4734},"minimark",[9,13,16,21,212,215,220,223,277,287,289,293,301,379,382,384,388,395,399,402,613,637,641,644,844,848,851,987,990,1100,1102,1106,1113,1185,1192,1196,1204,1270,1281,1345,1353,1402,1406,1409,1487,1490,1492,1496,1499,1503,1513,1520,1638,1641,1645,1648,1770,1774,1781,1923,1929,1999,2003,2009,2148,2162,2164,2168,2175,2293,2295,2299,2302,2520,2522,2526,2548,2566,2577,2601,2609,2620,2641,2659,2678,2690,2692,2696,2738,3026,3315,3510,3512,3517,3519,3524,3530,3536,3563,3568,3576,3581,3949,3951,3956,3961,3966,3971,4234,4239,4245,4249,4307,4309,4314,4319,4324,4329,4476,4482,4486,4728,4730],[10,11,12],"p",{},"Если map — это ассоциативный контейнер, то struct — способ объединить разнородные данные в единую сущность. В Go struct — это основа для построения любой доменной модели, и за простым синтаксисом скрывается несколько нетривиальных механизмов: embedding, struct tags и то, как компилятор раскладывает поля в памяти.",[14,15],"hr",{},[17,18,20],"h2",{"id":19},"базовый-синтаксис","Базовый синтаксис",[22,23,28],"pre",{"className":24,"code":25,"language":26,"meta":27,"style":27},"language-go shiki shiki-themes github-dark","type User struct {\n    ID       int\n    Name     string\n    Email    string\n    IsActive bool\n}\n\n\u002F\u002F Инициализация через именованные поля — предпочтительно\nu := User{\n    ID:       1,\n    Name:     \"Alice\",\n    Email:    \"alice@example.com\",\n    IsActive: true,\n}\n\n\u002F\u002F Позиционная инициализация — хрупко, избегать в продакшне\nu := User{1, \"Alice\", \"alice@example.com\", true}\n","go","",[29,30,31,51,60,69,77,86,92,99,106,120,133,145,156,167,172,177,183],"code",{"__ignoreMap":27},[32,33,36,40,44,47],"span",{"class":34,"line":35},"line",1,[32,37,39],{"class":38},"snl16","type",[32,41,43],{"class":42},"svObZ"," User",[32,45,46],{"class":38}," struct",[32,48,50],{"class":49},"s95oV"," {\n",[32,52,54,57],{"class":34,"line":53},2,[32,55,56],{"class":49},"    ID       ",[32,58,59],{"class":38},"int\n",[32,61,63,66],{"class":34,"line":62},3,[32,64,65],{"class":49},"    Name     ",[32,67,68],{"class":38},"string\n",[32,70,72,75],{"class":34,"line":71},4,[32,73,74],{"class":49},"    Email    ",[32,76,68],{"class":38},[32,78,80,83],{"class":34,"line":79},5,[32,81,82],{"class":49},"    IsActive ",[32,84,85],{"class":38},"bool\n",[32,87,89],{"class":34,"line":88},6,[32,90,91],{"class":49},"}\n",[32,93,95],{"class":34,"line":94},7,[32,96,98],{"emptyLinePlaceholder":97},true,"\n",[32,100,102],{"class":34,"line":101},8,[32,103,105],{"class":104},"sAwPA","\u002F\u002F Инициализация через именованные поля — предпочтительно\n",[32,107,109,112,115,117],{"class":34,"line":108},9,[32,110,111],{"class":49},"u ",[32,113,114],{"class":38},":=",[32,116,43],{"class":42},[32,118,119],{"class":49},"{\n",[32,121,123,126,130],{"class":34,"line":122},10,[32,124,125],{"class":49},"    ID:       ",[32,127,129],{"class":128},"sDLfK","1",[32,131,132],{"class":49},",\n",[32,134,136,139,143],{"class":34,"line":135},11,[32,137,138],{"class":49},"    Name:     ",[32,140,142],{"class":141},"sU2Wk","\"Alice\"",[32,144,132],{"class":49},[32,146,148,151,154],{"class":34,"line":147},12,[32,149,150],{"class":49},"    Email:    ",[32,152,153],{"class":141},"\"alice@example.com\"",[32,155,132],{"class":49},[32,157,159,162,165],{"class":34,"line":158},13,[32,160,161],{"class":49},"    IsActive: ",[32,163,164],{"class":128},"true",[32,166,132],{"class":49},[32,168,170],{"class":34,"line":169},14,[32,171,91],{"class":49},[32,173,175],{"class":34,"line":174},15,[32,176,98],{"emptyLinePlaceholder":97},[32,178,180],{"class":34,"line":179},16,[32,181,182],{"class":104},"\u002F\u002F Позиционная инициализация — хрупко, избегать в продакшне\n",[32,184,186,188,190,192,195,197,200,202,204,206,208,210],{"class":34,"line":185},17,[32,187,111],{"class":49},[32,189,114],{"class":38},[32,191,43],{"class":42},[32,193,194],{"class":49},"{",[32,196,129],{"class":128},[32,198,199],{"class":49},", ",[32,201,142],{"class":141},[32,203,199],{"class":49},[32,205,153],{"class":141},[32,207,199],{"class":49},[32,209,164],{"class":128},[32,211,91],{"class":49},[10,213,214],{},"Позиционная инициализация ломается при добавлении нового поля в структуру — компилятор не предупредит, если типы совпали случайно. Именованные поля — всегда безопаснее.",[216,217,219],"h3",{"id":218},"zero-value-структуры","Zero value структуры",[10,221,222],{},"Как и любой тип в Go, struct имеет zero value — каждое поле инициализируется своим нулевым значением:",[22,224,226],{"className":24,"code":225,"language":26,"meta":27,"style":27},"var u User\nfmt.Println(u.ID)       \u002F\u002F 0\nfmt.Println(u.Name)     \u002F\u002F \"\"\nfmt.Println(u.IsActive) \u002F\u002F false\n",[29,227,228,239,253,265],{"__ignoreMap":27},[32,229,230,233,236],{"class":34,"line":35},[32,231,232],{"class":38},"var",[32,234,235],{"class":49}," u ",[32,237,238],{"class":42},"User\n",[32,240,241,244,247,250],{"class":34,"line":53},[32,242,243],{"class":49},"fmt.",[32,245,246],{"class":42},"Println",[32,248,249],{"class":49},"(u.ID)       ",[32,251,252],{"class":104},"\u002F\u002F 0\n",[32,254,255,257,259,262],{"class":34,"line":62},[32,256,243],{"class":49},[32,258,246],{"class":42},[32,260,261],{"class":49},"(u.Name)     ",[32,263,264],{"class":104},"\u002F\u002F \"\"\n",[32,266,267,269,271,274],{"class":34,"line":71},[32,268,243],{"class":49},[32,270,246],{"class":42},[32,272,273],{"class":49},"(u.IsActive) ",[32,275,276],{"class":104},"\u002F\u002F false\n",[10,278,279,280,199,283,286],{},"Это позволяет строить конструкции, где zero value структуры уже является валидным начальным состоянием — паттерн, активно используемый в стандартной библиотеке (",[29,281,282],{},"sync.Mutex",[29,284,285],{},"bytes.Buffer"," и другие готовы к использованию без инициализации).",[14,288],{},[17,290,292],{"id":291},"struct-значимый-тип","Struct — значимый тип",[10,294,295,296,300],{},"Как и массив, struct является ",[297,298,299],"strong",{},"значимым типом",". При присвоении и передаче в функцию создаётся полная копия:",[22,302,304],{"className":24,"code":303,"language":26,"meta":27,"style":27},"a := User{ID: 1, Name: \"Alice\"}\nb := a        \u002F\u002F полная копия\nb.Name = \"Bob\"\n\nfmt.Println(a.Name) \u002F\u002F \"Alice\" — не изменился\nfmt.Println(b.Name) \u002F\u002F \"Bob\"\n",[29,305,306,327,340,351,355,367],{"__ignoreMap":27},[32,307,308,311,313,315,318,320,323,325],{"class":34,"line":35},[32,309,310],{"class":49},"a ",[32,312,114],{"class":38},[32,314,43],{"class":42},[32,316,317],{"class":49},"{ID: ",[32,319,129],{"class":128},[32,321,322],{"class":49},", Name: ",[32,324,142],{"class":141},[32,326,91],{"class":49},[32,328,329,332,334,337],{"class":34,"line":53},[32,330,331],{"class":49},"b ",[32,333,114],{"class":38},[32,335,336],{"class":49}," a        ",[32,338,339],{"class":104},"\u002F\u002F полная копия\n",[32,341,342,345,348],{"class":34,"line":62},[32,343,344],{"class":49},"b.Name ",[32,346,347],{"class":38},"=",[32,349,350],{"class":141}," \"Bob\"\n",[32,352,353],{"class":34,"line":71},[32,354,98],{"emptyLinePlaceholder":97},[32,356,357,359,361,364],{"class":34,"line":79},[32,358,243],{"class":49},[32,360,246],{"class":42},[32,362,363],{"class":49},"(a.Name) ",[32,365,366],{"class":104},"\u002F\u002F \"Alice\" — не изменился\n",[32,368,369,371,373,376],{"class":34,"line":88},[32,370,243],{"class":49},[32,372,246],{"class":42},[32,374,375],{"class":49},"(b.Name) ",[32,377,378],{"class":104},"\u002F\u002F \"Bob\"\n",[10,380,381],{},"Это важно для понимания того, когда использовать pointer receiver, а когда value receiver в методах. Большие структуры стоит передавать по указателю — копирование нескольких сотен байт на каждый вызов заметно в горячих путях.",[14,383],{},[17,385,387],{"id":386},"анонимные-поля-и-embedding","Анонимные поля и Embedding",[10,389,390,391,394],{},"Go не имеет классического наследования, но предоставляет ",[297,392,393],{},"embedding"," (встраивание) — механизм, который на практике решает ту же задачу повторного использования кода, но без иерархии типов.",[216,396,398],{"id":397},"анонимное-поле","Анонимное поле",[10,400,401],{},"Поле без имени — только тип. Компилятор автоматически генерирует одноимённый accessor:",[22,403,405],{"className":24,"code":404,"language":26,"meta":27,"style":27},"type Animal struct {\n    Name string\n}\n\nfunc (a Animal) Speak() string {\n    return a.Name + \" makes a sound\"\n}\n\ntype Dog struct {\n    Animal        \u002F\u002F анонимное поле — embedding\n    Breed  string\n}\n\nd := Dog{\n    Animal: Animal{Name: \"Rex\"},\n    Breed:  \"Labrador\",\n}\n\n\u002F\u002F Прямой доступ к полям и методам Animal через Dog\nfmt.Println(d.Name)    \u002F\u002F \"Rex\" — проброшено от Animal\nfmt.Println(d.Speak()) \u002F\u002F \"Rex makes a sound\" — метод Animal доступен на Dog\nfmt.Println(d.Animal.Name) \u002F\u002F \"Rex\" — явный доступ тоже работает\n",[29,406,407,418,425,429,433,461,475,479,483,494,502,509,513,517,528,544,554,558,563,569,582,600],{"__ignoreMap":27},[32,408,409,411,414,416],{"class":34,"line":35},[32,410,39],{"class":38},[32,412,413],{"class":42}," Animal",[32,415,46],{"class":38},[32,417,50],{"class":49},[32,419,420,423],{"class":34,"line":53},[32,421,422],{"class":49},"    Name ",[32,424,68],{"class":38},[32,426,427],{"class":34,"line":62},[32,428,91],{"class":49},[32,430,431],{"class":34,"line":71},[32,432,98],{"emptyLinePlaceholder":97},[32,434,435,438,441,444,447,450,453,456,459],{"class":34,"line":79},[32,436,437],{"class":38},"func",[32,439,440],{"class":49}," (",[32,442,310],{"class":443},"s9osk",[32,445,446],{"class":42},"Animal",[32,448,449],{"class":49},") ",[32,451,452],{"class":42},"Speak",[32,454,455],{"class":49},"() ",[32,457,458],{"class":38},"string",[32,460,50],{"class":49},[32,462,463,466,469,472],{"class":34,"line":88},[32,464,465],{"class":38},"    return",[32,467,468],{"class":49}," a.Name ",[32,470,471],{"class":38},"+",[32,473,474],{"class":141}," \" makes a sound\"\n",[32,476,477],{"class":34,"line":94},[32,478,91],{"class":49},[32,480,481],{"class":34,"line":101},[32,482,98],{"emptyLinePlaceholder":97},[32,484,485,487,490,492],{"class":34,"line":108},[32,486,39],{"class":38},[32,488,489],{"class":42}," Dog",[32,491,46],{"class":38},[32,493,50],{"class":49},[32,495,496,499],{"class":34,"line":122},[32,497,498],{"class":42},"    Animal",[32,500,501],{"class":104},"        \u002F\u002F анонимное поле — embedding\n",[32,503,504,507],{"class":34,"line":135},[32,505,506],{"class":49},"    Breed  ",[32,508,68],{"class":38},[32,510,511],{"class":34,"line":147},[32,512,91],{"class":49},[32,514,515],{"class":34,"line":158},[32,516,98],{"emptyLinePlaceholder":97},[32,518,519,522,524,526],{"class":34,"line":169},[32,520,521],{"class":49},"d ",[32,523,114],{"class":38},[32,525,489],{"class":42},[32,527,119],{"class":49},[32,529,530,533,535,538,541],{"class":34,"line":174},[32,531,532],{"class":49},"    Animal: ",[32,534,446],{"class":42},[32,536,537],{"class":49},"{Name: ",[32,539,540],{"class":141},"\"Rex\"",[32,542,543],{"class":49},"},\n",[32,545,546,549,552],{"class":34,"line":179},[32,547,548],{"class":49},"    Breed:  ",[32,550,551],{"class":141},"\"Labrador\"",[32,553,132],{"class":49},[32,555,556],{"class":34,"line":185},[32,557,91],{"class":49},[32,559,561],{"class":34,"line":560},18,[32,562,98],{"emptyLinePlaceholder":97},[32,564,566],{"class":34,"line":565},19,[32,567,568],{"class":104},"\u002F\u002F Прямой доступ к полям и методам Animal через Dog\n",[32,570,572,574,576,579],{"class":34,"line":571},20,[32,573,243],{"class":49},[32,575,246],{"class":42},[32,577,578],{"class":49},"(d.Name)    ",[32,580,581],{"class":104},"\u002F\u002F \"Rex\" — проброшено от Animal\n",[32,583,585,587,589,592,594,597],{"class":34,"line":584},21,[32,586,243],{"class":49},[32,588,246],{"class":42},[32,590,591],{"class":49},"(d.",[32,593,452],{"class":42},[32,595,596],{"class":49},"()) ",[32,598,599],{"class":104},"\u002F\u002F \"Rex makes a sound\" — метод Animal доступен на Dog\n",[32,601,603,605,607,610],{"class":34,"line":602},22,[32,604,243],{"class":49},[32,606,246],{"class":42},[32,608,609],{"class":49},"(d.Animal.Name) ",[32,611,612],{"class":104},"\u002F\u002F \"Rex\" — явный доступ тоже работает\n",[10,614,615,616,619,620,623,624,626,627,629,630,632,633,636],{},"Важно: это ",[297,617,618],{},"не наследование",". ",[29,621,622],{},"Dog"," не является подтипом ",[29,625,446],{},". Вы не можете передать ",[29,628,622],{}," туда, где ожидается ",[29,631,446],{},". Embedding — это ",[297,634,635],{},"делегирование",": компилятор автоматически генерирует обёртки, вызывающие методы встроенного типа.",[216,638,640],{"id":639},"проброс-интерфейсов-через-embedding","Проброс интерфейсов через embedding",[10,642,643],{},"Главная практическая польза embedding — реализация интерфейсов:",[22,645,647],{"className":24,"code":646,"language":26,"meta":27,"style":27},"type Logger interface {\n    Log(msg string)\n}\n\ntype ConsoleLogger struct{}\n\nfunc (l ConsoleLogger) Log(msg string) {\n    fmt.Println(\"[LOG]\", msg)\n}\n\ntype Service struct {\n    ConsoleLogger  \u002F\u002F Service автоматически реализует Logger\n    name string\n}\n\nvar _ Logger = Service{} \u002F\u002F проверка на этапе компиляции\n\ns := Service{name: \"payments\"}\ns.Log(\"started\") \u002F\u002F [LOG] started\n",[29,648,649,661,678,682,686,698,702,728,743,747,751,762,770,777,781,785,806,810,827],{"__ignoreMap":27},[32,650,651,653,656,659],{"class":34,"line":35},[32,652,39],{"class":38},[32,654,655],{"class":42}," Logger",[32,657,658],{"class":38}," interface",[32,660,50],{"class":49},[32,662,663,666,669,672,675],{"class":34,"line":53},[32,664,665],{"class":42},"    Log",[32,667,668],{"class":49},"(",[32,670,671],{"class":443},"msg",[32,673,674],{"class":38}," string",[32,676,677],{"class":49},")\n",[32,679,680],{"class":34,"line":62},[32,681,91],{"class":49},[32,683,684],{"class":34,"line":71},[32,685,98],{"emptyLinePlaceholder":97},[32,687,688,690,693,695],{"class":34,"line":79},[32,689,39],{"class":38},[32,691,692],{"class":42}," ConsoleLogger",[32,694,46],{"class":38},[32,696,697],{"class":49},"{}\n",[32,699,700],{"class":34,"line":88},[32,701,98],{"emptyLinePlaceholder":97},[32,703,704,706,708,711,714,716,719,721,723,725],{"class":34,"line":94},[32,705,437],{"class":38},[32,707,440],{"class":49},[32,709,710],{"class":443},"l ",[32,712,713],{"class":42},"ConsoleLogger",[32,715,449],{"class":49},[32,717,718],{"class":42},"Log",[32,720,668],{"class":49},[32,722,671],{"class":443},[32,724,674],{"class":38},[32,726,727],{"class":49},") {\n",[32,729,730,733,735,737,740],{"class":34,"line":101},[32,731,732],{"class":49},"    fmt.",[32,734,246],{"class":42},[32,736,668],{"class":49},[32,738,739],{"class":141},"\"[LOG]\"",[32,741,742],{"class":49},", msg)\n",[32,744,745],{"class":34,"line":108},[32,746,91],{"class":49},[32,748,749],{"class":34,"line":122},[32,750,98],{"emptyLinePlaceholder":97},[32,752,753,755,758,760],{"class":34,"line":135},[32,754,39],{"class":38},[32,756,757],{"class":42}," Service",[32,759,46],{"class":38},[32,761,50],{"class":49},[32,763,764,767],{"class":34,"line":147},[32,765,766],{"class":42},"    ConsoleLogger",[32,768,769],{"class":104},"  \u002F\u002F Service автоматически реализует Logger\n",[32,771,772,775],{"class":34,"line":158},[32,773,774],{"class":49},"    name ",[32,776,68],{"class":38},[32,778,779],{"class":34,"line":169},[32,780,91],{"class":49},[32,782,783],{"class":34,"line":174},[32,784,98],{"emptyLinePlaceholder":97},[32,786,787,789,792,795,798,800,803],{"class":34,"line":179},[32,788,232],{"class":38},[32,790,791],{"class":49}," _ ",[32,793,794],{"class":42},"Logger",[32,796,797],{"class":38}," =",[32,799,757],{"class":42},[32,801,802],{"class":49},"{} ",[32,804,805],{"class":104},"\u002F\u002F проверка на этапе компиляции\n",[32,807,808],{"class":34,"line":185},[32,809,98],{"emptyLinePlaceholder":97},[32,811,812,815,817,819,822,825],{"class":34,"line":560},[32,813,814],{"class":49},"s ",[32,816,114],{"class":38},[32,818,757],{"class":42},[32,820,821],{"class":49},"{name: ",[32,823,824],{"class":141},"\"payments\"",[32,826,91],{"class":49},[32,828,829,832,834,836,839,841],{"class":34,"line":565},[32,830,831],{"class":49},"s.",[32,833,718],{"class":42},[32,835,668],{"class":49},[32,837,838],{"class":141},"\"started\"",[32,840,449],{"class":49},[32,842,843],{"class":104},"\u002F\u002F [LOG] started\n",[216,845,847],{"id":846},"разрешение-конфликтов-имён","Разрешение конфликтов имён",[10,849,850],{},"Если два встроенных типа имеют поле или метод с одинаковым именем, компилятор требует явного обращения:",[22,852,854],{"className":24,"code":853,"language":26,"meta":27,"style":27},"type A struct{ Value int }\ntype B struct{ Value int }\n\ntype C struct {\n    A\n    B\n}\n\nc := C{A: A{1}, B: B{2}}\n\u002F\u002F fmt.Println(c.Value) \u002F\u002F Ошибка: ambiguous selector c.Value\nfmt.Println(c.A.Value) \u002F\u002F 1 — явное обращение\nfmt.Println(c.B.Value) \u002F\u002F 2\n",[29,855,856,874,889,893,904,909,914,918,922,955,963,975],{"__ignoreMap":27},[32,857,858,860,863,865,868,871],{"class":34,"line":35},[32,859,39],{"class":38},[32,861,862],{"class":42}," A",[32,864,46],{"class":38},[32,866,867],{"class":49},"{ Value ",[32,869,870],{"class":38},"int",[32,872,873],{"class":49}," }\n",[32,875,876,878,881,883,885,887],{"class":34,"line":53},[32,877,39],{"class":38},[32,879,880],{"class":42}," B",[32,882,46],{"class":38},[32,884,867],{"class":49},[32,886,870],{"class":38},[32,888,873],{"class":49},[32,890,891],{"class":34,"line":62},[32,892,98],{"emptyLinePlaceholder":97},[32,894,895,897,900,902],{"class":34,"line":71},[32,896,39],{"class":38},[32,898,899],{"class":42}," C",[32,901,46],{"class":38},[32,903,50],{"class":49},[32,905,906],{"class":34,"line":79},[32,907,908],{"class":42},"    A\n",[32,910,911],{"class":34,"line":88},[32,912,913],{"class":42},"    B\n",[32,915,916],{"class":34,"line":94},[32,917,91],{"class":49},[32,919,920],{"class":34,"line":101},[32,921,98],{"emptyLinePlaceholder":97},[32,923,924,927,929,931,934,937,939,941,944,947,949,952],{"class":34,"line":108},[32,925,926],{"class":49},"c ",[32,928,114],{"class":38},[32,930,899],{"class":42},[32,932,933],{"class":49},"{A: ",[32,935,936],{"class":42},"A",[32,938,194],{"class":49},[32,940,129],{"class":128},[32,942,943],{"class":49},"}, B: ",[32,945,946],{"class":42},"B",[32,948,194],{"class":49},[32,950,951],{"class":128},"2",[32,953,954],{"class":49},"}}\n",[32,956,957,960],{"class":34,"line":122},[32,958,959],{"class":104},"\u002F\u002F fmt.Println(c.Value)",[32,961,962],{"class":104}," \u002F\u002F Ошибка: ambiguous selector c.Value\n",[32,964,965,967,969,972],{"class":34,"line":135},[32,966,243],{"class":49},[32,968,246],{"class":42},[32,970,971],{"class":49},"(c.A.Value) ",[32,973,974],{"class":104},"\u002F\u002F 1 — явное обращение\n",[32,976,977,979,981,984],{"class":34,"line":147},[32,978,243],{"class":49},[32,980,246],{"class":42},[32,982,983],{"class":49},"(c.B.Value) ",[32,985,986],{"class":104},"\u002F\u002F 2\n",[10,988,989],{},"При этом если поле есть у самой структуры и у встроенного типа — побеждает поле структуры (ближайший уровень):",[22,991,993],{"className":24,"code":992,"language":26,"meta":27,"style":27},"type Base struct{ ID int }\n\ntype Entity struct {\n    Base\n    ID string \u002F\u002F перекрывает Base.ID\n}\n\ne := Entity{Base: Base{ID: 1}, ID: \"abc\"}\nfmt.Println(e.ID)      \u002F\u002F \"abc\" — поле Entity\nfmt.Println(e.Base.ID) \u002F\u002F 1 — явный доступ к Base\n",[29,994,995,1011,1015,1026,1031,1041,1045,1049,1076,1088],{"__ignoreMap":27},[32,996,997,999,1002,1004,1007,1009],{"class":34,"line":35},[32,998,39],{"class":38},[32,1000,1001],{"class":42}," Base",[32,1003,46],{"class":38},[32,1005,1006],{"class":49},"{ ID ",[32,1008,870],{"class":38},[32,1010,873],{"class":49},[32,1012,1013],{"class":34,"line":53},[32,1014,98],{"emptyLinePlaceholder":97},[32,1016,1017,1019,1022,1024],{"class":34,"line":62},[32,1018,39],{"class":38},[32,1020,1021],{"class":42}," Entity",[32,1023,46],{"class":38},[32,1025,50],{"class":49},[32,1027,1028],{"class":34,"line":71},[32,1029,1030],{"class":42},"    Base\n",[32,1032,1033,1036,1038],{"class":34,"line":79},[32,1034,1035],{"class":49},"    ID ",[32,1037,458],{"class":38},[32,1039,1040],{"class":104}," \u002F\u002F перекрывает Base.ID\n",[32,1042,1043],{"class":34,"line":88},[32,1044,91],{"class":49},[32,1046,1047],{"class":34,"line":94},[32,1048,98],{"emptyLinePlaceholder":97},[32,1050,1051,1054,1056,1058,1061,1064,1066,1068,1071,1074],{"class":34,"line":101},[32,1052,1053],{"class":49},"e ",[32,1055,114],{"class":38},[32,1057,1021],{"class":42},[32,1059,1060],{"class":49},"{Base: ",[32,1062,1063],{"class":42},"Base",[32,1065,317],{"class":49},[32,1067,129],{"class":128},[32,1069,1070],{"class":49},"}, ID: ",[32,1072,1073],{"class":141},"\"abc\"",[32,1075,91],{"class":49},[32,1077,1078,1080,1082,1085],{"class":34,"line":108},[32,1079,243],{"class":49},[32,1081,246],{"class":42},[32,1083,1084],{"class":49},"(e.ID)      ",[32,1086,1087],{"class":104},"\u002F\u002F \"abc\" — поле Entity\n",[32,1089,1090,1092,1094,1097],{"class":34,"line":122},[32,1091,243],{"class":49},[32,1093,246],{"class":42},[32,1095,1096],{"class":49},"(e.Base.ID) ",[32,1098,1099],{"class":104},"\u002F\u002F 1 — явный доступ к Base\n",[14,1101],{},[17,1103,1105],{"id":1104},"struct-tags","Struct tags",[10,1107,1108,1109,1112],{},"Struct tags — это метаданные для полей, которые не влияют на поведение компилятора, но читаются библиотеками через ",[29,1110,1111],{},"reflect"," в рантайме:",[22,1114,1116],{"className":24,"code":1115,"language":26,"meta":27,"style":27},"type User struct {\n    ID        int    `json:\"id\" db:\"user_id\" validate:\"required\"`\n    Name      string `json:\"name\" validate:\"required,min=2,max=100\"`\n    Password  string `json:\"-\"`                  \u002F\u002F исключить из JSON\n    CreatedAt time.Time `json:\"created_at,omitempty\"` \u002F\u002F пропустить если zero\n}\n",[29,1117,1118,1128,1138,1148,1161,1181],{"__ignoreMap":27},[32,1119,1120,1122,1124,1126],{"class":34,"line":35},[32,1121,39],{"class":38},[32,1123,43],{"class":42},[32,1125,46],{"class":38},[32,1127,50],{"class":49},[32,1129,1130,1133,1135],{"class":34,"line":53},[32,1131,1132],{"class":49},"    ID        ",[32,1134,870],{"class":38},[32,1136,1137],{"class":141},"    `json:\"id\" db:\"user_id\" validate:\"required\"`\n",[32,1139,1140,1143,1145],{"class":34,"line":62},[32,1141,1142],{"class":49},"    Name      ",[32,1144,458],{"class":38},[32,1146,1147],{"class":141}," `json:\"name\" validate:\"required,min=2,max=100\"`\n",[32,1149,1150,1153,1155,1158],{"class":34,"line":71},[32,1151,1152],{"class":49},"    Password  ",[32,1154,458],{"class":38},[32,1156,1157],{"class":141}," `json:\"-\"`",[32,1159,1160],{"class":104},"                  \u002F\u002F исключить из JSON\n",[32,1162,1163,1166,1169,1172,1175,1178],{"class":34,"line":79},[32,1164,1165],{"class":49},"    CreatedAt ",[32,1167,1168],{"class":42},"time",[32,1170,1171],{"class":49},".",[32,1173,1174],{"class":42},"Time",[32,1176,1177],{"class":141}," `json:\"created_at,omitempty\"`",[32,1179,1180],{"class":104}," \u002F\u002F пропустить если zero\n",[32,1182,1183],{"class":34,"line":88},[32,1184,91],{"class":49},[10,1186,1187,1188,1191],{},"Формат тега: ",[29,1189,1190],{},"key:\"value\"",", несколько тегов через пробел. Значение — произвольная строка, интерпретируемая конкретной библиотекой.",[216,1193,1195],{"id":1194},"распространённые-теги","Распространённые теги",[10,1197,1198],{},[297,1199,1200,1203],{},[29,1201,1202],{},"encoding\u002Fjson",":",[22,1205,1207],{"className":24,"code":1206,"language":26,"meta":27,"style":27},"type Response struct {\n    Status  string `json:\"status\"`\n    Data    any    `json:\"data,omitempty\"` \u002F\u002F пропустить если nil\u002Fzero\n    Error   string `json:\"error,omitempty\"`\n    interno string `json:\"-\"`             \u002F\u002F всегда исключить\n}\n",[29,1208,1209,1220,1230,1244,1254,1266],{"__ignoreMap":27},[32,1210,1211,1213,1216,1218],{"class":34,"line":35},[32,1212,39],{"class":38},[32,1214,1215],{"class":42}," Response",[32,1217,46],{"class":38},[32,1219,50],{"class":49},[32,1221,1222,1225,1227],{"class":34,"line":53},[32,1223,1224],{"class":49},"    Status  ",[32,1226,458],{"class":38},[32,1228,1229],{"class":141}," `json:\"status\"`\n",[32,1231,1232,1235,1238,1241],{"class":34,"line":62},[32,1233,1234],{"class":49},"    Data    ",[32,1236,1237],{"class":42},"any",[32,1239,1240],{"class":141},"    `json:\"data,omitempty\"`",[32,1242,1243],{"class":104}," \u002F\u002F пропустить если nil\u002Fzero\n",[32,1245,1246,1249,1251],{"class":34,"line":71},[32,1247,1248],{"class":49},"    Error   ",[32,1250,458],{"class":38},[32,1252,1253],{"class":141}," `json:\"error,omitempty\"`\n",[32,1255,1256,1259,1261,1263],{"class":34,"line":79},[32,1257,1258],{"class":49},"    interno ",[32,1260,458],{"class":38},[32,1262,1157],{"class":141},[32,1264,1265],{"class":104},"             \u002F\u002F всегда исключить\n",[32,1267,1268],{"class":34,"line":88},[32,1269,91],{"class":49},[10,1271,1272],{},[297,1273,1274,1277,1278,1203],{},[29,1275,1276],{},"database\u002Fsql"," и ",[29,1279,1280],{},"sqlx",[22,1282,1284],{"className":24,"code":1283,"language":26,"meta":27,"style":27},"type User struct {\n    ID    int    `db:\"id\"`\n    Email string `db:\"email\"`\n}\n\n\u002F\u002F sqlx сканирует строки по тегу db, а не по имени поля\nrows.StructScan(&user)\n",[29,1285,1286,1296,1306,1316,1320,1324,1329],{"__ignoreMap":27},[32,1287,1288,1290,1292,1294],{"class":34,"line":35},[32,1289,39],{"class":38},[32,1291,43],{"class":42},[32,1293,46],{"class":38},[32,1295,50],{"class":49},[32,1297,1298,1301,1303],{"class":34,"line":53},[32,1299,1300],{"class":49},"    ID    ",[32,1302,870],{"class":38},[32,1304,1305],{"class":141},"    `db:\"id\"`\n",[32,1307,1308,1311,1313],{"class":34,"line":62},[32,1309,1310],{"class":49},"    Email ",[32,1312,458],{"class":38},[32,1314,1315],{"class":141}," `db:\"email\"`\n",[32,1317,1318],{"class":34,"line":71},[32,1319,91],{"class":49},[32,1321,1322],{"class":34,"line":79},[32,1323,98],{"emptyLinePlaceholder":97},[32,1325,1326],{"class":34,"line":88},[32,1327,1328],{"class":104},"\u002F\u002F sqlx сканирует строки по тегу db, а не по имени поля\n",[32,1330,1331,1334,1337,1339,1342],{"class":34,"line":94},[32,1332,1333],{"class":49},"rows.",[32,1335,1336],{"class":42},"StructScan",[32,1338,668],{"class":49},[32,1340,1341],{"class":38},"&",[32,1343,1344],{"class":49},"user)\n",[10,1346,1347],{},[297,1348,1349,1352],{},[29,1350,1351],{},"validate"," (github.com\u002Fgo-playground\u002Fvalidator):",[22,1354,1356],{"className":24,"code":1355,"language":26,"meta":27,"style":27},"type CreateUserRequest struct {\n    Email    string `json:\"email\"    validate:\"required,email\"`\n    Age      int    `json:\"age\"      validate:\"required,min=18,max=120\"`\n    Password string `json:\"password\" validate:\"required,min=8\"`\n}\n",[29,1357,1358,1369,1378,1388,1398],{"__ignoreMap":27},[32,1359,1360,1362,1365,1367],{"class":34,"line":35},[32,1361,39],{"class":38},[32,1363,1364],{"class":42}," CreateUserRequest",[32,1366,46],{"class":38},[32,1368,50],{"class":49},[32,1370,1371,1373,1375],{"class":34,"line":53},[32,1372,74],{"class":49},[32,1374,458],{"class":38},[32,1376,1377],{"class":141}," `json:\"email\"    validate:\"required,email\"`\n",[32,1379,1380,1383,1385],{"class":34,"line":62},[32,1381,1382],{"class":49},"    Age      ",[32,1384,870],{"class":38},[32,1386,1387],{"class":141},"    `json:\"age\"      validate:\"required,min=18,max=120\"`\n",[32,1389,1390,1393,1395],{"class":34,"line":71},[32,1391,1392],{"class":49},"    Password ",[32,1394,458],{"class":38},[32,1396,1397],{"class":141}," `json:\"password\" validate:\"required,min=8\"`\n",[32,1399,1400],{"class":34,"line":79},[32,1401,91],{"class":49},[216,1403,1405],{"id":1404},"чтение-тегов-через-reflect","Чтение тегов через reflect",[10,1407,1408],{},"Под капотом теги читаются так:",[22,1410,1412],{"className":24,"code":1411,"language":26,"meta":27,"style":27},"t := reflect.TypeOf(User{})\nfield, _ := t.FieldByName(\"Name\")\ntag := field.Tag.Get(\"json\") \u002F\u002F \"name\"\nfmt.Println(tag)\n",[29,1413,1414,1435,1455,1478],{"__ignoreMap":27},[32,1415,1416,1419,1421,1424,1427,1429,1432],{"class":34,"line":35},[32,1417,1418],{"class":49},"t ",[32,1420,114],{"class":38},[32,1422,1423],{"class":49}," reflect.",[32,1425,1426],{"class":42},"TypeOf",[32,1428,668],{"class":49},[32,1430,1431],{"class":42},"User",[32,1433,1434],{"class":49},"{})\n",[32,1436,1437,1440,1442,1445,1448,1450,1453],{"class":34,"line":53},[32,1438,1439],{"class":49},"field, _ ",[32,1441,114],{"class":38},[32,1443,1444],{"class":49}," t.",[32,1446,1447],{"class":42},"FieldByName",[32,1449,668],{"class":49},[32,1451,1452],{"class":141},"\"Name\"",[32,1454,677],{"class":49},[32,1456,1457,1460,1462,1465,1468,1470,1473,1475],{"class":34,"line":62},[32,1458,1459],{"class":49},"tag ",[32,1461,114],{"class":38},[32,1463,1464],{"class":49}," field.Tag.",[32,1466,1467],{"class":42},"Get",[32,1469,668],{"class":49},[32,1471,1472],{"class":141},"\"json\"",[32,1474,449],{"class":49},[32,1476,1477],{"class":104},"\u002F\u002F \"name\"\n",[32,1479,1480,1482,1484],{"class":34,"line":71},[32,1481,243],{"class":49},[32,1483,246],{"class":42},[32,1485,1486],{"class":49},"(tag)\n",[10,1488,1489],{},"Именно поэтому теги доступны только в рантайме — компилятор их игнорирует.",[14,1491],{},[17,1493,1495],{"id":1494},"выравнивание-и-раскладка-в-памяти","Выравнивание и раскладка в памяти",[10,1497,1498],{},"Это тема, которую редко знают джуны, но часто спрашивают на Middle+ и Senior. Понимание выравнивания позволяет сэкономить память без изменения логики.",[216,1500,1502],{"id":1501},"что-такое-выравнивание","Что такое выравнивание",[10,1504,1505,1506,1509,1510,1512],{},"Процессор читает память словами фиксированного размера (обычно 8 байт на 64-битной архитектуре). Доступ к данным эффективен, когда их адрес кратен их размеру. ",[29,1507,1508],{},"int64"," по адресу 0 — эффективно. ",[29,1511,1508],{}," по адресу 1 — нет: процессор вынужден читать два слова и склеивать.",[10,1514,1515,1516,1519],{},"Чтобы избежать невыровненного доступа, компилятор вставляет ",[297,1517,1518],{},"padding"," — байты-заглушки между полями:",[22,1521,1523],{"className":24,"code":1522,"language":26,"meta":27,"style":27},"type Bad struct {\n    A bool    \u002F\u002F 1 байт\n              \u002F\u002F 7 байт padding (до выравнивания int64)\n    B int64   \u002F\u002F 8 байт\n    C bool    \u002F\u002F 1 байт\n              \u002F\u002F 7 байт padding (до выравнивания следующей структуры)\n}\n\u002F\u002F Итого: 24 байта\n\ntype Good struct {\n    B int64   \u002F\u002F 8 байт\n    A bool    \u002F\u002F 1 байт\n    C bool    \u002F\u002F 1 байт\n              \u002F\u002F 6 байт padding\n}\n\u002F\u002F Итого: 16 байт\n",[29,1524,1525,1536,1547,1552,1562,1571,1576,1580,1585,1589,1600,1608,1616,1624,1629,1633],{"__ignoreMap":27},[32,1526,1527,1529,1532,1534],{"class":34,"line":35},[32,1528,39],{"class":38},[32,1530,1531],{"class":42}," Bad",[32,1533,46],{"class":38},[32,1535,50],{"class":49},[32,1537,1538,1541,1544],{"class":34,"line":53},[32,1539,1540],{"class":49},"    A ",[32,1542,1543],{"class":38},"bool",[32,1545,1546],{"class":104},"    \u002F\u002F 1 байт\n",[32,1548,1549],{"class":34,"line":62},[32,1550,1551],{"class":104},"              \u002F\u002F 7 байт padding (до выравнивания int64)\n",[32,1553,1554,1557,1559],{"class":34,"line":71},[32,1555,1556],{"class":49},"    B ",[32,1558,1508],{"class":38},[32,1560,1561],{"class":104},"   \u002F\u002F 8 байт\n",[32,1563,1564,1567,1569],{"class":34,"line":79},[32,1565,1566],{"class":49},"    C ",[32,1568,1543],{"class":38},[32,1570,1546],{"class":104},[32,1572,1573],{"class":34,"line":88},[32,1574,1575],{"class":104},"              \u002F\u002F 7 байт padding (до выравнивания следующей структуры)\n",[32,1577,1578],{"class":34,"line":94},[32,1579,91],{"class":49},[32,1581,1582],{"class":34,"line":101},[32,1583,1584],{"class":104},"\u002F\u002F Итого: 24 байта\n",[32,1586,1587],{"class":34,"line":108},[32,1588,98],{"emptyLinePlaceholder":97},[32,1590,1591,1593,1596,1598],{"class":34,"line":122},[32,1592,39],{"class":38},[32,1594,1595],{"class":42}," Good",[32,1597,46],{"class":38},[32,1599,50],{"class":49},[32,1601,1602,1604,1606],{"class":34,"line":135},[32,1603,1556],{"class":49},[32,1605,1508],{"class":38},[32,1607,1561],{"class":104},[32,1609,1610,1612,1614],{"class":34,"line":147},[32,1611,1540],{"class":49},[32,1613,1543],{"class":38},[32,1615,1546],{"class":104},[32,1617,1618,1620,1622],{"class":34,"line":158},[32,1619,1566],{"class":49},[32,1621,1543],{"class":38},[32,1623,1546],{"class":104},[32,1625,1626],{"class":34,"line":169},[32,1627,1628],{"class":104},"              \u002F\u002F 6 байт padding\n",[32,1630,1631],{"class":34,"line":174},[32,1632,91],{"class":49},[32,1634,1635],{"class":34,"line":179},[32,1636,1637],{"class":104},"\u002F\u002F Итого: 16 байт\n",[10,1639,1640],{},"Экономия 8 байт — треть размера структуры. Для миллионов объектов это ощутимо.",[216,1642,1644],{"id":1643},"правила-выравнивания","Правила выравнивания",[10,1646,1647],{},"Выравнивание поля равно его размеру (но не более 8 байт на 64-битной платформе):",[1649,1650,1651,1667],"table",{},[1652,1653,1654],"thead",{},[1655,1656,1657,1661,1664],"tr",{},[1658,1659,1660],"th",{},"Тип",[1658,1662,1663],{},"Размер",[1658,1665,1666],{},"Выравнивание",[1668,1669,1670,1688,1703,1721,1738,1749,1761],"tbody",{},[1655,1671,1672,1683,1686],{},[1673,1674,1675,199,1677,199,1680],"td",{},[29,1676,1543],{},[29,1678,1679],{},"byte",[29,1681,1682],{},"int8",[1673,1684,1685],{},"1 байт",[1673,1687,1685],{},[1655,1689,1690,1698,1701],{},[1673,1691,1692,199,1695],{},[29,1693,1694],{},"int16",[29,1696,1697],{},"uint16",[1673,1699,1700],{},"2 байта",[1673,1702,1700],{},[1655,1704,1705,1716,1719],{},[1673,1706,1707,199,1710,199,1713],{},[29,1708,1709],{},"int32",[29,1711,1712],{},"uint32",[29,1714,1715],{},"float32",[1673,1717,1718],{},"4 байта",[1673,1720,1718],{},[1655,1722,1723,1733,1736],{},[1673,1724,1725,199,1727,199,1730],{},[29,1726,1508],{},[29,1728,1729],{},"uint64",[29,1731,1732],{},"float64",[1673,1734,1735],{},"8 байт",[1673,1737,1735],{},[1655,1739,1740,1744,1747],{},[1673,1741,1742],{},[29,1743,458],{},[1673,1745,1746],{},"16 байт",[1673,1748,1735],{},[1655,1750,1751,1756,1759],{},[1673,1752,1753],{},[29,1754,1755],{},"slice",[1673,1757,1758],{},"24 байта",[1673,1760,1735],{},[1655,1762,1763,1766,1768],{},[1673,1764,1765],{},"указатель",[1673,1767,1735],{},[1673,1769,1735],{},[216,1771,1773],{"id":1772},"практический-пример-оптимизации","Практический пример оптимизации",[10,1775,1776,1777,1780],{},"Хорошее практическое правило: ",[297,1778,1779],{},"от большего к меньшему",". Сначала 8-байтовые поля, потом 4-байтовые, потом 2-байтовые, потом 1-байтовые:",[22,1782,1784],{"className":24,"code":1783,"language":26,"meta":27,"style":27},"\u002F\u002F Плохо — 40 байт из-за padding\ntype Request struct {\n    IsAdmin  bool      \u002F\u002F 1 + 7 padding\n    UserID   int64     \u002F\u002F 8\n    IsActive bool      \u002F\u002F 1 + 3 padding\n    Score    float32   \u002F\u002F 4\n    Name     string    \u002F\u002F 16\n}\n\n\u002F\u002F Хорошо — 32 байта\ntype Request struct {\n    Name     string    \u002F\u002F 16\n    UserID   int64     \u002F\u002F 8\n    Score    float32   \u002F\u002F 4\n    IsAdmin  bool      \u002F\u002F 1\n    IsActive bool      \u002F\u002F 1\n                       \u002F\u002F 2 байта padding\n}\n",[29,1785,1786,1791,1802,1812,1822,1831,1841,1850,1854,1858,1863,1873,1881,1889,1897,1906,1914,1919],{"__ignoreMap":27},[32,1787,1788],{"class":34,"line":35},[32,1789,1790],{"class":104},"\u002F\u002F Плохо — 40 байт из-за padding\n",[32,1792,1793,1795,1798,1800],{"class":34,"line":53},[32,1794,39],{"class":38},[32,1796,1797],{"class":42}," Request",[32,1799,46],{"class":38},[32,1801,50],{"class":49},[32,1803,1804,1807,1809],{"class":34,"line":62},[32,1805,1806],{"class":49},"    IsAdmin  ",[32,1808,1543],{"class":38},[32,1810,1811],{"class":104},"      \u002F\u002F 1 + 7 padding\n",[32,1813,1814,1817,1819],{"class":34,"line":71},[32,1815,1816],{"class":49},"    UserID   ",[32,1818,1508],{"class":38},[32,1820,1821],{"class":104},"     \u002F\u002F 8\n",[32,1823,1824,1826,1828],{"class":34,"line":79},[32,1825,82],{"class":49},[32,1827,1543],{"class":38},[32,1829,1830],{"class":104},"      \u002F\u002F 1 + 3 padding\n",[32,1832,1833,1836,1838],{"class":34,"line":88},[32,1834,1835],{"class":49},"    Score    ",[32,1837,1715],{"class":38},[32,1839,1840],{"class":104},"   \u002F\u002F 4\n",[32,1842,1843,1845,1847],{"class":34,"line":94},[32,1844,65],{"class":49},[32,1846,458],{"class":38},[32,1848,1849],{"class":104},"    \u002F\u002F 16\n",[32,1851,1852],{"class":34,"line":101},[32,1853,91],{"class":49},[32,1855,1856],{"class":34,"line":108},[32,1857,98],{"emptyLinePlaceholder":97},[32,1859,1860],{"class":34,"line":122},[32,1861,1862],{"class":104},"\u002F\u002F Хорошо — 32 байта\n",[32,1864,1865,1867,1869,1871],{"class":34,"line":135},[32,1866,39],{"class":38},[32,1868,1797],{"class":42},[32,1870,46],{"class":38},[32,1872,50],{"class":49},[32,1874,1875,1877,1879],{"class":34,"line":147},[32,1876,65],{"class":49},[32,1878,458],{"class":38},[32,1880,1849],{"class":104},[32,1882,1883,1885,1887],{"class":34,"line":158},[32,1884,1816],{"class":49},[32,1886,1508],{"class":38},[32,1888,1821],{"class":104},[32,1890,1891,1893,1895],{"class":34,"line":169},[32,1892,1835],{"class":49},[32,1894,1715],{"class":38},[32,1896,1840],{"class":104},[32,1898,1899,1901,1903],{"class":34,"line":174},[32,1900,1806],{"class":49},[32,1902,1543],{"class":38},[32,1904,1905],{"class":104},"      \u002F\u002F 1\n",[32,1907,1908,1910,1912],{"class":34,"line":179},[32,1909,82],{"class":49},[32,1911,1543],{"class":38},[32,1913,1905],{"class":104},[32,1915,1916],{"class":34,"line":185},[32,1917,1918],{"class":104},"                       \u002F\u002F 2 байта padding\n",[32,1920,1921],{"class":34,"line":560},[32,1922,91],{"class":49},[10,1924,1925,1926,1203],{},"Проверить размер и выравнивание можно через ",[29,1927,1928],{},"unsafe",[22,1930,1932],{"className":24,"code":1931,"language":26,"meta":27,"style":27},"fmt.Println(unsafe.Sizeof(Request{}))     \u002F\u002F размер в байтах\nfmt.Println(unsafe.Alignof(Request{}))    \u002F\u002F выравнивание структуры\nfmt.Println(unsafe.Offsetof(Request{}.Score)) \u002F\u002F смещение поля\n",[29,1933,1934,1957,1978],{"__ignoreMap":27},[32,1935,1936,1938,1940,1943,1946,1948,1951,1954],{"class":34,"line":35},[32,1937,243],{"class":49},[32,1939,246],{"class":42},[32,1941,1942],{"class":49},"(unsafe.",[32,1944,1945],{"class":42},"Sizeof",[32,1947,668],{"class":49},[32,1949,1950],{"class":42},"Request",[32,1952,1953],{"class":49},"{}))     ",[32,1955,1956],{"class":104},"\u002F\u002F размер в байтах\n",[32,1958,1959,1961,1963,1965,1968,1970,1972,1975],{"class":34,"line":53},[32,1960,243],{"class":49},[32,1962,246],{"class":42},[32,1964,1942],{"class":49},[32,1966,1967],{"class":42},"Alignof",[32,1969,668],{"class":49},[32,1971,1950],{"class":42},[32,1973,1974],{"class":49},"{}))    ",[32,1976,1977],{"class":104},"\u002F\u002F выравнивание структуры\n",[32,1979,1980,1982,1984,1986,1989,1991,1993,1996],{"class":34,"line":62},[32,1981,243],{"class":49},[32,1983,246],{"class":42},[32,1985,1942],{"class":49},[32,1987,1988],{"class":42},"Offsetof",[32,1990,668],{"class":49},[32,1992,1950],{"class":42},[32,1994,1995],{"class":49},"{}.Score)) ",[32,1997,1998],{"class":104},"\u002F\u002F смещение поля\n",[216,2000,2002],{"id":2001},"пустая-структура-особый-случай","Пустая структура — особый случай",[10,2004,2005,2008],{},[29,2006,2007],{},"struct{}"," имеет нулевой размер и широко используется как сигнальный тип:",[22,2010,2012],{"className":24,"code":2011,"language":26,"meta":27,"style":27},"\u002F\u002F Канал-сигнал (не передаёт данных)\ndone := make(chan struct{})\ngo func() {\n    \u002F\u002F работа\n    close(done)\n}()\n\u003C-done\n\n\u002F\u002F Set через map (экономим память на значениях)\nvisited := make(map[string]struct{})\nvisited[\"node1\"] = struct{}{}\n\n\u002F\u002F Глобальная переменная zero-size не занимает адрес в heap\nvar zeroValue struct{}\n",[29,2013,2014,2019,2038,2048,2053,2061,2066,2074,2078,2083,2110,2128,2132,2137],{"__ignoreMap":27},[32,2015,2016],{"class":34,"line":35},[32,2017,2018],{"class":104},"\u002F\u002F Канал-сигнал (не передаёт данных)\n",[32,2020,2021,2024,2026,2029,2031,2034,2036],{"class":34,"line":53},[32,2022,2023],{"class":49},"done ",[32,2025,114],{"class":38},[32,2027,2028],{"class":42}," make",[32,2030,668],{"class":49},[32,2032,2033],{"class":38},"chan",[32,2035,46],{"class":38},[32,2037,1434],{"class":49},[32,2039,2040,2042,2045],{"class":34,"line":62},[32,2041,26],{"class":38},[32,2043,2044],{"class":38}," func",[32,2046,2047],{"class":49},"() {\n",[32,2049,2050],{"class":34,"line":71},[32,2051,2052],{"class":104},"    \u002F\u002F работа\n",[32,2054,2055,2058],{"class":34,"line":79},[32,2056,2057],{"class":42},"    close",[32,2059,2060],{"class":49},"(done)\n",[32,2062,2063],{"class":34,"line":88},[32,2064,2065],{"class":49},"}()\n",[32,2067,2068,2071],{"class":34,"line":94},[32,2069,2070],{"class":38},"\u003C-",[32,2072,2073],{"class":49},"done\n",[32,2075,2076],{"class":34,"line":101},[32,2077,98],{"emptyLinePlaceholder":97},[32,2079,2080],{"class":34,"line":108},[32,2081,2082],{"class":104},"\u002F\u002F Set через map (экономим память на значениях)\n",[32,2084,2085,2088,2090,2092,2094,2097,2100,2102,2105,2108],{"class":34,"line":122},[32,2086,2087],{"class":49},"visited ",[32,2089,114],{"class":38},[32,2091,2028],{"class":42},[32,2093,668],{"class":49},[32,2095,2096],{"class":38},"map",[32,2098,2099],{"class":49},"[",[32,2101,458],{"class":38},[32,2103,2104],{"class":49},"]",[32,2106,2107],{"class":38},"struct",[32,2109,1434],{"class":49},[32,2111,2112,2115,2118,2121,2123,2125],{"class":34,"line":135},[32,2113,2114],{"class":49},"visited[",[32,2116,2117],{"class":141},"\"node1\"",[32,2119,2120],{"class":49},"] ",[32,2122,347],{"class":38},[32,2124,46],{"class":38},[32,2126,2127],{"class":49},"{}{}\n",[32,2129,2130],{"class":34,"line":147},[32,2131,98],{"emptyLinePlaceholder":97},[32,2133,2134],{"class":34,"line":158},[32,2135,2136],{"class":104},"\u002F\u002F Глобальная переменная zero-size не занимает адрес в heap\n",[32,2138,2139,2141,2144,2146],{"class":34,"line":169},[32,2140,232],{"class":38},[32,2142,2143],{"class":49}," zeroValue ",[32,2145,2107],{"class":38},[32,2147,697],{"class":49},[10,2149,2150,2151,2153,2154,2157,2158,2161],{},"Интересный момент: два указателя на ",[29,2152,2007],{}," могут указывать на один и тот же адрес — ",[29,2155,2156],{},"unsafe.Sizeof(struct{}{})"," всегда 0, и компилятор оптимизирует это, используя ",[29,2159,2160],{},"runtime.zerobase"," как общий адрес для всех zero-size значений.",[14,2163],{},[17,2165,2167],{"id":2166},"сравнение-структур","Сравнение структур",[10,2169,2170,2171,2174],{},"Структуры можно сравнивать через ",[29,2172,2173],{},"==",", если все их поля — comparable типы:",[22,2176,2178],{"className":24,"code":2177,"language":26,"meta":27,"style":27},"type Point struct{ X, Y int }\n\np1 := Point{1, 2}\np2 := Point{1, 2}\nfmt.Println(p1 == p2) \u002F\u002F true — сравниваются поля по значению\n\ntype Polygon struct {\n    Points []Point \u002F\u002F слайс — не comparable\n}\n\u002F\u002F p1 == p2 \u002F\u002F Ошибка компиляции\n",[29,2179,2180,2196,2200,2219,2238,2255,2259,2270,2281,2285],{"__ignoreMap":27},[32,2181,2182,2184,2187,2189,2192,2194],{"class":34,"line":35},[32,2183,39],{"class":38},[32,2185,2186],{"class":42}," Point",[32,2188,46],{"class":38},[32,2190,2191],{"class":49},"{ X, Y ",[32,2193,870],{"class":38},[32,2195,873],{"class":49},[32,2197,2198],{"class":34,"line":53},[32,2199,98],{"emptyLinePlaceholder":97},[32,2201,2202,2205,2207,2209,2211,2213,2215,2217],{"class":34,"line":62},[32,2203,2204],{"class":49},"p1 ",[32,2206,114],{"class":38},[32,2208,2186],{"class":42},[32,2210,194],{"class":49},[32,2212,129],{"class":128},[32,2214,199],{"class":49},[32,2216,951],{"class":128},[32,2218,91],{"class":49},[32,2220,2221,2224,2226,2228,2230,2232,2234,2236],{"class":34,"line":71},[32,2222,2223],{"class":49},"p2 ",[32,2225,114],{"class":38},[32,2227,2186],{"class":42},[32,2229,194],{"class":49},[32,2231,129],{"class":128},[32,2233,199],{"class":49},[32,2235,951],{"class":128},[32,2237,91],{"class":49},[32,2239,2240,2242,2244,2247,2249,2252],{"class":34,"line":79},[32,2241,243],{"class":49},[32,2243,246],{"class":42},[32,2245,2246],{"class":49},"(p1 ",[32,2248,2173],{"class":38},[32,2250,2251],{"class":49}," p2) ",[32,2253,2254],{"class":104},"\u002F\u002F true — сравниваются поля по значению\n",[32,2256,2257],{"class":34,"line":88},[32,2258,98],{"emptyLinePlaceholder":97},[32,2260,2261,2263,2266,2268],{"class":34,"line":94},[32,2262,39],{"class":38},[32,2264,2265],{"class":42}," Polygon",[32,2267,46],{"class":38},[32,2269,50],{"class":49},[32,2271,2272,2275,2278],{"class":34,"line":101},[32,2273,2274],{"class":49},"    Points []",[32,2276,2277],{"class":42},"Point",[32,2279,2280],{"class":104}," \u002F\u002F слайс — не comparable\n",[32,2282,2283],{"class":34,"line":108},[32,2284,91],{"class":49},[32,2286,2287,2290],{"class":34,"line":122},[32,2288,2289],{"class":104},"\u002F\u002F p1 == p2",[32,2291,2292],{"class":104}," \u002F\u002F Ошибка компиляции\n",[14,2294],{},[17,2296,2298],{"id":2297},"анонимные-структуры","Анонимные структуры",[10,2300,2301],{},"Go позволяет объявлять структуры без имени — прямо в месте использования. Это удобно для одноразовых данных:",[22,2303,2305],{"className":24,"code":2304,"language":26,"meta":27,"style":27},"\u002F\u002F Временная группировка данных в тесте\ntestCases := []struct {\n    input    string\n    expected int\n}{\n    {\"hello\", 5},\n    {\"world!\", 6},\n}\n\nfor _, tc := range testCases {\n    result := len(tc.input)\n    if result != tc.expected {\n        t.Errorf(\"got %d, want %d\", result, tc.expected)\n    }\n}\n\n\u002F\u002F Декодирование JSON без объявления типа\nvar resp struct {\n    Status string `json:\"status\"`\n    Count  int    `json:\"count\"`\n}\njson.Unmarshal(data, &resp)\n",[29,2306,2307,2312,2326,2333,2340,2345,2360,2374,2378,2382,2398,2411,2425,2452,2457,2461,2465,2470,2481,2490,2500,2504],{"__ignoreMap":27},[32,2308,2309],{"class":34,"line":35},[32,2310,2311],{"class":104},"\u002F\u002F Временная группировка данных в тесте\n",[32,2313,2314,2317,2319,2322,2324],{"class":34,"line":53},[32,2315,2316],{"class":49},"testCases ",[32,2318,114],{"class":38},[32,2320,2321],{"class":49}," []",[32,2323,2107],{"class":38},[32,2325,50],{"class":49},[32,2327,2328,2331],{"class":34,"line":62},[32,2329,2330],{"class":49},"    input    ",[32,2332,68],{"class":38},[32,2334,2335,2338],{"class":34,"line":71},[32,2336,2337],{"class":49},"    expected ",[32,2339,59],{"class":38},[32,2341,2342],{"class":34,"line":79},[32,2343,2344],{"class":49},"}{\n",[32,2346,2347,2350,2353,2355,2358],{"class":34,"line":88},[32,2348,2349],{"class":49},"    {",[32,2351,2352],{"class":141},"\"hello\"",[32,2354,199],{"class":49},[32,2356,2357],{"class":128},"5",[32,2359,543],{"class":49},[32,2361,2362,2364,2367,2369,2372],{"class":34,"line":94},[32,2363,2349],{"class":49},[32,2365,2366],{"class":141},"\"world!\"",[32,2368,199],{"class":49},[32,2370,2371],{"class":128},"6",[32,2373,543],{"class":49},[32,2375,2376],{"class":34,"line":101},[32,2377,91],{"class":49},[32,2379,2380],{"class":34,"line":108},[32,2381,98],{"emptyLinePlaceholder":97},[32,2383,2384,2387,2390,2392,2395],{"class":34,"line":122},[32,2385,2386],{"class":38},"for",[32,2388,2389],{"class":49}," _, tc ",[32,2391,114],{"class":38},[32,2393,2394],{"class":38}," range",[32,2396,2397],{"class":49}," testCases {\n",[32,2399,2400,2403,2405,2408],{"class":34,"line":135},[32,2401,2402],{"class":49},"    result ",[32,2404,114],{"class":38},[32,2406,2407],{"class":42}," len",[32,2409,2410],{"class":49},"(tc.input)\n",[32,2412,2413,2416,2419,2422],{"class":34,"line":147},[32,2414,2415],{"class":38},"    if",[32,2417,2418],{"class":49}," result ",[32,2420,2421],{"class":38},"!=",[32,2423,2424],{"class":49}," tc.expected {\n",[32,2426,2427,2430,2433,2435,2438,2441,2444,2446,2449],{"class":34,"line":158},[32,2428,2429],{"class":49},"        t.",[32,2431,2432],{"class":42},"Errorf",[32,2434,668],{"class":49},[32,2436,2437],{"class":141},"\"got ",[32,2439,2440],{"class":128},"%d",[32,2442,2443],{"class":141},", want ",[32,2445,2440],{"class":128},[32,2447,2448],{"class":141},"\"",[32,2450,2451],{"class":49},", result, tc.expected)\n",[32,2453,2454],{"class":34,"line":169},[32,2455,2456],{"class":49},"    }\n",[32,2458,2459],{"class":34,"line":174},[32,2460,91],{"class":49},[32,2462,2463],{"class":34,"line":179},[32,2464,98],{"emptyLinePlaceholder":97},[32,2466,2467],{"class":34,"line":185},[32,2468,2469],{"class":104},"\u002F\u002F Декодирование JSON без объявления типа\n",[32,2471,2472,2474,2477,2479],{"class":34,"line":560},[32,2473,232],{"class":38},[32,2475,2476],{"class":49}," resp ",[32,2478,2107],{"class":38},[32,2480,50],{"class":49},[32,2482,2483,2486,2488],{"class":34,"line":565},[32,2484,2485],{"class":49},"    Status ",[32,2487,458],{"class":38},[32,2489,1229],{"class":141},[32,2491,2492,2495,2497],{"class":34,"line":571},[32,2493,2494],{"class":49},"    Count  ",[32,2496,870],{"class":38},[32,2498,2499],{"class":141},"    `json:\"count\"`\n",[32,2501,2502],{"class":34,"line":584},[32,2503,91],{"class":49},[32,2505,2506,2509,2512,2515,2517],{"class":34,"line":602},[32,2507,2508],{"class":49},"json.",[32,2510,2511],{"class":42},"Unmarshal",[32,2513,2514],{"class":49},"(data, ",[32,2516,1341],{"class":38},[32,2518,2519],{"class":49},"resp)\n",[14,2521],{},[17,2523,2525],{"id":2524},"вопросы-на-собеседовании","Вопросы на собеседовании",[10,2527,2528,2531,2534,2535,2537,2538,623,2540,2542,2543,629,2545,2547],{},[297,2529,2530],{},"Q: Чем embedding отличается от наследования?",[2532,2533],"br",{},"\nA: Embedding — это делегирование, а не наследование. ",[29,2536,622],{}," со встроенным ",[29,2539,446],{},[29,2541,446],{}," — передать ",[29,2544,622],{},[29,2546,446],{},", нельзя. Компилятор лишь генерирует обёртки, которые проксируют вызовы методов и доступ к полям встроенного типа. Никакой иерархии типов нет.",[10,2549,2550,2553,2555,2556,2559,2560,2562,2563,2565],{},[297,2551,2552],{},"Q: Что такое zero value структуры и зачем это нужно?",[2532,2554],{},"\nA: При объявлении ",[29,2557,2558],{},"var s MyStruct"," каждое поле получает своё zero value. Это позволяет проектировать типы так, чтобы их zero value было валидным начальным состоянием — как ",[29,2561,282],{}," или ",[29,2564,285],{},", готовые к использованию без явной инициализации.",[10,2567,2568,2571,2573,2574,1171],{},[297,2569,2570],{},"Q: Struct — значимый или ссылочный тип?",[2532,2572],{},"\nA: Значимый (value type). При присвоении и передаче в функцию создаётся полная копия всех полей. Чтобы избежать копирования и\u002Fили разрешить мутацию оригинала — передают указатель ",[29,2575,2576],{},"*MyStruct",[10,2578,2579,2582,2584,2585,2587,2588,2591,2592,2594,2595,2597,2598,2600],{},[297,2580,2581],{},"Q: Что такое struct tags? Как они работают?",[2532,2583],{},"\nA: Строковые метаданные для полей, игнорируемые компилятором, но читаемые библиотеками через ",[29,2586,1111],{}," в рантайме. Формат: ",[29,2589,2590],{},"`key:\"value\"`",". Используются в ",[29,2593,1202],{}," для маппинга имён, в ",[29,2596,1276],{},"\u002F",[29,2599,1280],{}," для сканирования строк, в валидаторах и ORM.",[10,2602,2603,2606,2608],{},[297,2604,2605],{},"Q: Что такое padding и почему он появляется?",[2532,2607],{},"\nA: Байты-заглушки, которые компилятор вставляет между полями структуры для выравнивания доступа к памяти. Процессор читает данные эффективно только если их адрес кратен их размеру. Padding обеспечивает это условие за счёт увеличения размера структуры.",[10,2610,2611,2614,2616,2617,1171],{},[297,2612,2613],{},"Q: Как оптимизировать размер структуры?",[2532,2615],{},"\nA: Расположить поля от большего размера к меньшему — 8-байтовые первыми, 1-байтовые последними. Это минимизирует количество padding-байт. Можно проверить через ",[29,2618,2619],{},"unsafe.Sizeof",[10,2621,2622,2628,2630,2631,2634,2635,2638,2639,1171],{},[297,2623,2624,2625,2627],{},"Q: Что такое ",[29,2626,2007],{},"? Где применяется?",[2532,2629],{},"\nA: Структура нулевого размера — занимает 0 байт. Используется как: сигнальный тип в каналах (",[29,2632,2633],{},"chan struct{}","), значение в set-map (",[29,2636,2637],{},"map[K]struct{}","), маркер в паттернах. Все zero-size значения в Go указывают на один адрес ",[29,2640,2160],{},[10,2642,2643,2649,2651,2652,2654,2655,2658],{},[297,2644,2645,2646,2648],{},"Q: Можно ли сравнить две структуры через ",[29,2647,2173],{},"?",[2532,2650],{},"\nA: Да, если все поля структуры — comparable типы (базовые типы, массивы, другие comparable структуры). Если хотя бы одно поле — слайс, map или функция — компилятор запретит сравнение через ",[29,2653,2173],{},". Тогда нужен ",[29,2656,2657],{},"reflect.DeepEqual"," или ручное сравнение.",[10,2660,2661,2664,2666,2667,2670,2671,2562,2674,2677],{},[297,2662,2663],{},"Q: Как разрешается конфликт имён при embedding нескольких типов?",[2532,2665],{},"\nA: Если два встроенных типа имеют поле или метод с одинаковым именем — компилятор выдаёт ошибку ",[29,2668,2669],{},"ambiguous selector"," при попытке обратиться к нему без квалификатора. Нужно явно указывать: ",[29,2672,2673],{},"s.A.Value",[29,2675,2676],{},"s.B.Value",". Если поле есть и в самой структуре, и во встроенном типе — приоритет у структуры (ближайший уровень вложенности).",[10,2679,2680,2683,2685,2686,2689],{},[297,2681,2682],{},"Q: Почему нельзя взять адрес поля структуры из map и изменить его?",[2532,2684],{},"\nA: Элементы map non-addressable: при росте таблицы Go может переместить данные, и старый адрес стал бы невалидным. Поэтому ",[29,2687,2688],{},"m[\"key\"].Field = value"," — ошибка компиляции. Нужно достать копию, изменить, положить обратно.",[14,2691],{},[17,2693,2695],{"id":2694},"практика","Практика",[2697,2698,2701,2704,2723],"quiz",{"answer":951,"id":2699,"xp":2700},"basics-structs-q1","10",[10,2702,2703],{},"Структура — это значимый или ссылочный тип в Go?",[2705,2706,2707],"template",{"v-slot:options":27},[2708,2709,2710,2714,2717,2720],"ul",{},[2711,2712,2713],"li",{},"Ссылочный — при передаче в функцию передаётся указатель",[2711,2715,2716],{},"Значимый — при передаче в функцию создаётся полная копия",[2711,2718,2719],{},"Зависит от размера структуры",[2711,2721,2722],{},"Зависит от типов полей",[2705,2724,2725],{"v-slot:explanation":27},[10,2726,2727,2728,2731,2732,2735,2736,1171],{},"Структура в Go — ",[297,2729,2730],{},"значимый тип"," (value type). При присвоении ",[29,2733,2734],{},"b := a"," и при передаче в функцию создаётся полная копия всех полей. Чтобы избежать копирования или разрешить мутацию оригинала — передают указатель ",[29,2737,2576],{},[2739,2740,2744,2747,3004],"predict",{"answer":2741,"id":2742,"xp":2743},"Rex says: ...\\nI am Rex says: ...\\nI am Rex says: ...","basics-structs-p1","15",[10,2745,2746],{},"Угадай вывод программы. Обрати внимание на embedding.",[2705,2748,2749],{"v-slot:code":27},[22,2750,2752],{"className":24,"code":2751,"language":26,"meta":27,"style":27},"package main\n\nimport \"fmt\"\n\ntype Animal struct{ Name string }\n\nfunc (a Animal) Speak() string   { return a.Name + \" says: ...\" }\nfunc (a Animal) Describe() string { return \"I am \" + a.Speak() }\n\ntype Dog struct{ Animal }\n\nfunc (d Dog) Speak() string { return d.Name + \" says: Woof!\" }\n\nfunc main() {\n    d := Dog{Animal: Animal{Name: \"Rex\"}}\n    fmt.Println(d.Speak())\n    fmt.Println(d.Describe())\n    fmt.Println(d.Animal.Speak())\n}\n",[29,2753,2754,2762,2766,2780,2784,2799,2803,2836,2874,2878,2893,2897,2929,2933,2942,2962,2975,2987,3000],{"__ignoreMap":27},[32,2755,2756,2759],{"class":34,"line":35},[32,2757,2758],{"class":38},"package",[32,2760,2761],{"class":42}," main\n",[32,2763,2764],{"class":34,"line":53},[32,2765,98],{"emptyLinePlaceholder":97},[32,2767,2768,2771,2774,2777],{"class":34,"line":62},[32,2769,2770],{"class":38},"import",[32,2772,2773],{"class":141}," \"",[32,2775,2776],{"class":42},"fmt",[32,2778,2779],{"class":141},"\"\n",[32,2781,2782],{"class":34,"line":71},[32,2783,98],{"emptyLinePlaceholder":97},[32,2785,2786,2788,2790,2792,2795,2797],{"class":34,"line":79},[32,2787,39],{"class":38},[32,2789,413],{"class":42},[32,2791,46],{"class":38},[32,2793,2794],{"class":49},"{ Name ",[32,2796,458],{"class":38},[32,2798,873],{"class":49},[32,2800,2801],{"class":34,"line":88},[32,2802,98],{"emptyLinePlaceholder":97},[32,2804,2805,2807,2809,2811,2813,2815,2817,2819,2821,2824,2827,2829,2831,2834],{"class":34,"line":94},[32,2806,437],{"class":38},[32,2808,440],{"class":49},[32,2810,310],{"class":443},[32,2812,446],{"class":42},[32,2814,449],{"class":49},[32,2816,452],{"class":42},[32,2818,455],{"class":49},[32,2820,458],{"class":38},[32,2822,2823],{"class":49},"   { ",[32,2825,2826],{"class":38},"return",[32,2828,468],{"class":49},[32,2830,471],{"class":38},[32,2832,2833],{"class":141}," \" says: ...\"",[32,2835,873],{"class":49},[32,2837,2838,2840,2842,2844,2846,2848,2851,2853,2855,2858,2860,2863,2866,2869,2871],{"class":34,"line":101},[32,2839,437],{"class":38},[32,2841,440],{"class":49},[32,2843,310],{"class":443},[32,2845,446],{"class":42},[32,2847,449],{"class":49},[32,2849,2850],{"class":42},"Describe",[32,2852,455],{"class":49},[32,2854,458],{"class":38},[32,2856,2857],{"class":49}," { ",[32,2859,2826],{"class":38},[32,2861,2862],{"class":141}," \"I am \"",[32,2864,2865],{"class":38}," +",[32,2867,2868],{"class":49}," a.",[32,2870,452],{"class":42},[32,2872,2873],{"class":49},"() }\n",[32,2875,2876],{"class":34,"line":108},[32,2877,98],{"emptyLinePlaceholder":97},[32,2879,2880,2882,2884,2886,2889,2891],{"class":34,"line":122},[32,2881,39],{"class":38},[32,2883,489],{"class":42},[32,2885,46],{"class":38},[32,2887,2888],{"class":49},"{ ",[32,2890,446],{"class":42},[32,2892,873],{"class":49},[32,2894,2895],{"class":34,"line":135},[32,2896,98],{"emptyLinePlaceholder":97},[32,2898,2899,2901,2903,2905,2907,2909,2911,2913,2915,2917,2919,2922,2924,2927],{"class":34,"line":147},[32,2900,437],{"class":38},[32,2902,440],{"class":49},[32,2904,521],{"class":443},[32,2906,622],{"class":42},[32,2908,449],{"class":49},[32,2910,452],{"class":42},[32,2912,455],{"class":49},[32,2914,458],{"class":38},[32,2916,2857],{"class":49},[32,2918,2826],{"class":38},[32,2920,2921],{"class":49}," d.Name ",[32,2923,471],{"class":38},[32,2925,2926],{"class":141}," \" says: Woof!\"",[32,2928,873],{"class":49},[32,2930,2931],{"class":34,"line":158},[32,2932,98],{"emptyLinePlaceholder":97},[32,2934,2935,2937,2940],{"class":34,"line":169},[32,2936,437],{"class":38},[32,2938,2939],{"class":42}," main",[32,2941,2047],{"class":49},[32,2943,2944,2947,2949,2951,2954,2956,2958,2960],{"class":34,"line":174},[32,2945,2946],{"class":49},"    d ",[32,2948,114],{"class":38},[32,2950,489],{"class":42},[32,2952,2953],{"class":49},"{Animal: ",[32,2955,446],{"class":42},[32,2957,537],{"class":49},[32,2959,540],{"class":141},[32,2961,954],{"class":49},[32,2963,2964,2966,2968,2970,2972],{"class":34,"line":179},[32,2965,732],{"class":49},[32,2967,246],{"class":42},[32,2969,591],{"class":49},[32,2971,452],{"class":42},[32,2973,2974],{"class":49},"())\n",[32,2976,2977,2979,2981,2983,2985],{"class":34,"line":185},[32,2978,732],{"class":49},[32,2980,246],{"class":42},[32,2982,591],{"class":49},[32,2984,2850],{"class":42},[32,2986,2974],{"class":49},[32,2988,2989,2991,2993,2996,2998],{"class":34,"line":560},[32,2990,732],{"class":49},[32,2992,246],{"class":42},[32,2994,2995],{"class":49},"(d.Animal.",[32,2997,452],{"class":42},[32,2999,2974],{"class":49},[32,3001,3002],{"class":34,"line":565},[32,3003,91],{"class":49},[2705,3005,3006],{"v-slot:hint":27},[10,3007,3008,3011,3012,3015,3016,3019,3020,3022,3023,3025],{},[29,3009,3010],{},"Dog.Describe()"," не определён — вызывается ",[29,3013,3014],{},"Animal.Describe()",". Внутри него ",[29,3017,3018],{},"a.Speak()"," — это вызов на значении типа ",[29,3021,446],{},", Go не знает про ",[29,3024,622],{},". Нет виртуальных методов!",[3027,3028,3032,3046,3285],"code-task",{"expected":3029,"id":3030,"xp":3031},"&{Alice 30 alice@example.com} \u003Cnil>\\n\u003Cnil> invalid age","basics-structs-ct1","20",[10,3033,3034,3035,3038,3039,3042,3043,1171],{},"Реализуй конструктор ",[29,3036,3037],{},"NewUser",", который принимает имя, возраст и email, валидирует их и возвращает ",[29,3040,3041],{},"(*User, error)",". Правила: имя не пустое, возраст 0–150, email содержит ",[29,3044,3045],{},"@",[2705,3047,3048],{"v-slot:template":27},[22,3049,3051],{"className":24,"code":3050,"language":26,"meta":27,"style":27},"package main\n\nimport (\n    \"errors\"\n    \"fmt\"\n    \"strings\"\n)\n\ntype User struct {\n    Name  string\n    Age   int\n    Email string\n}\n\nfunc NewUser(name string, age int, email string) (*User, error) {\n    \u002F\u002F твой код здесь\n}\n\nfunc main() {\n    u, err := NewUser(\"Alice\", 30, \"alice@example.com\")\n    fmt.Println(u, err)\n\n    u, err = NewUser(\"Alice\", -5, \"alice@example.com\")\n    fmt.Println(u, err)\n}\n",[29,3052,3053,3059,3063,3070,3080,3088,3097,3101,3105,3115,3122,3129,3135,3139,3143,3187,3192,3196,3200,3208,3232,3241,3245,3271,3280],{"__ignoreMap":27},[32,3054,3055,3057],{"class":34,"line":35},[32,3056,2758],{"class":38},[32,3058,2761],{"class":42},[32,3060,3061],{"class":34,"line":53},[32,3062,98],{"emptyLinePlaceholder":97},[32,3064,3065,3067],{"class":34,"line":62},[32,3066,2770],{"class":38},[32,3068,3069],{"class":49}," (\n",[32,3071,3072,3075,3078],{"class":34,"line":71},[32,3073,3074],{"class":141},"    \"",[32,3076,3077],{"class":42},"errors",[32,3079,2779],{"class":141},[32,3081,3082,3084,3086],{"class":34,"line":79},[32,3083,3074],{"class":141},[32,3085,2776],{"class":42},[32,3087,2779],{"class":141},[32,3089,3090,3092,3095],{"class":34,"line":88},[32,3091,3074],{"class":141},[32,3093,3094],{"class":42},"strings",[32,3096,2779],{"class":141},[32,3098,3099],{"class":34,"line":94},[32,3100,677],{"class":49},[32,3102,3103],{"class":34,"line":101},[32,3104,98],{"emptyLinePlaceholder":97},[32,3106,3107,3109,3111,3113],{"class":34,"line":108},[32,3108,39],{"class":38},[32,3110,43],{"class":42},[32,3112,46],{"class":38},[32,3114,50],{"class":49},[32,3116,3117,3120],{"class":34,"line":122},[32,3118,3119],{"class":49},"    Name  ",[32,3121,68],{"class":38},[32,3123,3124,3127],{"class":34,"line":135},[32,3125,3126],{"class":49},"    Age   ",[32,3128,59],{"class":38},[32,3130,3131,3133],{"class":34,"line":147},[32,3132,1310],{"class":49},[32,3134,68],{"class":38},[32,3136,3137],{"class":34,"line":158},[32,3138,91],{"class":49},[32,3140,3141],{"class":34,"line":169},[32,3142,98],{"emptyLinePlaceholder":97},[32,3144,3145,3147,3150,3152,3155,3157,3159,3162,3165,3167,3170,3172,3175,3178,3180,3182,3185],{"class":34,"line":174},[32,3146,437],{"class":38},[32,3148,3149],{"class":42}," NewUser",[32,3151,668],{"class":49},[32,3153,3154],{"class":443},"name",[32,3156,674],{"class":38},[32,3158,199],{"class":49},[32,3160,3161],{"class":443},"age",[32,3163,3164],{"class":38}," int",[32,3166,199],{"class":49},[32,3168,3169],{"class":443},"email",[32,3171,674],{"class":38},[32,3173,3174],{"class":49},") (",[32,3176,3177],{"class":38},"*",[32,3179,1431],{"class":42},[32,3181,199],{"class":49},[32,3183,3184],{"class":38},"error",[32,3186,727],{"class":49},[32,3188,3189],{"class":34,"line":179},[32,3190,3191],{"class":104},"    \u002F\u002F твой код здесь\n",[32,3193,3194],{"class":34,"line":185},[32,3195,91],{"class":49},[32,3197,3198],{"class":34,"line":560},[32,3199,98],{"emptyLinePlaceholder":97},[32,3201,3202,3204,3206],{"class":34,"line":565},[32,3203,437],{"class":38},[32,3205,2939],{"class":42},[32,3207,2047],{"class":49},[32,3209,3210,3213,3215,3217,3219,3221,3223,3226,3228,3230],{"class":34,"line":571},[32,3211,3212],{"class":49},"    u, err ",[32,3214,114],{"class":38},[32,3216,3149],{"class":42},[32,3218,668],{"class":49},[32,3220,142],{"class":141},[32,3222,199],{"class":49},[32,3224,3225],{"class":128},"30",[32,3227,199],{"class":49},[32,3229,153],{"class":141},[32,3231,677],{"class":49},[32,3233,3234,3236,3238],{"class":34,"line":584},[32,3235,732],{"class":49},[32,3237,246],{"class":42},[32,3239,3240],{"class":49},"(u, err)\n",[32,3242,3243],{"class":34,"line":602},[32,3244,98],{"emptyLinePlaceholder":97},[32,3246,3248,3250,3252,3254,3256,3258,3260,3263,3265,3267,3269],{"class":34,"line":3247},23,[32,3249,3212],{"class":49},[32,3251,347],{"class":38},[32,3253,3149],{"class":42},[32,3255,668],{"class":49},[32,3257,142],{"class":141},[32,3259,199],{"class":49},[32,3261,3262],{"class":38},"-",[32,3264,2357],{"class":128},[32,3266,199],{"class":49},[32,3268,153],{"class":141},[32,3270,677],{"class":49},[32,3272,3274,3276,3278],{"class":34,"line":3273},24,[32,3275,732],{"class":49},[32,3277,246],{"class":42},[32,3279,3240],{"class":49},[32,3281,3283],{"class":34,"line":3282},25,[32,3284,91],{"class":49},[2705,3286,3287],{"v-slot:hints":27},[2708,3288,3289,3296,3302,3308],{},[2711,3290,3291,3292,3295],{},"Используй ",[29,3293,3294],{},"strings.TrimSpace(name) == \"\""," для проверки имени",[2711,3297,3298,3299],{},"Проверь ",[29,3300,3301],{},"age \u003C 0 || age > 150",[2711,3303,3291,3304,3307],{},[29,3305,3306],{},"strings.Contains(email, \"@\")"," для email",[2711,3309,3310,3311,3314],{},"Возвращай ",[29,3312,3313],{},"nil, errors.New(\"...\")"," при ошибке",[3316,3317,3321,3324,3483],"code-fix",{"expected":3318,"id":3319,"xp":3320},"Alice: 31","basics-structs-cf1","25",[10,3322,3323],{},"Исправь код: функция должна обновлять возраст в оригинальной структуре, а не в копии.",[2705,3325,3326],{"v-slot:code":27},[22,3327,3329],{"className":24,"code":3328,"language":26,"meta":27,"style":27},"package main\n\nimport \"fmt\"\n\ntype User struct {\n    Name string\n    Age  int\n}\n\nfunc birthday(u User) {\n    u.Age++\n}\n\nfunc main() {\n    u := User{Name: \"Alice\", Age: 30}\n    birthday(u)\n    fmt.Printf(\"%s: %d\\n\", u.Name, u.Age)\n}\n",[29,3330,3331,3337,3341,3351,3355,3365,3371,3378,3382,3386,3402,3410,3414,3418,3426,3446,3454,3479],{"__ignoreMap":27},[32,3332,3333,3335],{"class":34,"line":35},[32,3334,2758],{"class":38},[32,3336,2761],{"class":42},[32,3338,3339],{"class":34,"line":53},[32,3340,98],{"emptyLinePlaceholder":97},[32,3342,3343,3345,3347,3349],{"class":34,"line":62},[32,3344,2770],{"class":38},[32,3346,2773],{"class":141},[32,3348,2776],{"class":42},[32,3350,2779],{"class":141},[32,3352,3353],{"class":34,"line":71},[32,3354,98],{"emptyLinePlaceholder":97},[32,3356,3357,3359,3361,3363],{"class":34,"line":79},[32,3358,39],{"class":38},[32,3360,43],{"class":42},[32,3362,46],{"class":38},[32,3364,50],{"class":49},[32,3366,3367,3369],{"class":34,"line":88},[32,3368,422],{"class":49},[32,3370,68],{"class":38},[32,3372,3373,3376],{"class":34,"line":94},[32,3374,3375],{"class":49},"    Age  ",[32,3377,59],{"class":38},[32,3379,3380],{"class":34,"line":101},[32,3381,91],{"class":49},[32,3383,3384],{"class":34,"line":108},[32,3385,98],{"emptyLinePlaceholder":97},[32,3387,3388,3390,3393,3395,3398,3400],{"class":34,"line":122},[32,3389,437],{"class":38},[32,3391,3392],{"class":42}," birthday",[32,3394,668],{"class":49},[32,3396,3397],{"class":443},"u",[32,3399,43],{"class":42},[32,3401,727],{"class":49},[32,3403,3404,3407],{"class":34,"line":135},[32,3405,3406],{"class":49},"    u.Age",[32,3408,3409],{"class":38},"++\n",[32,3411,3412],{"class":34,"line":147},[32,3413,91],{"class":49},[32,3415,3416],{"class":34,"line":158},[32,3417,98],{"emptyLinePlaceholder":97},[32,3419,3420,3422,3424],{"class":34,"line":169},[32,3421,437],{"class":38},[32,3423,2939],{"class":42},[32,3425,2047],{"class":49},[32,3427,3428,3431,3433,3435,3437,3439,3442,3444],{"class":34,"line":174},[32,3429,3430],{"class":49},"    u ",[32,3432,114],{"class":38},[32,3434,43],{"class":42},[32,3436,537],{"class":49},[32,3438,142],{"class":141},[32,3440,3441],{"class":49},", Age: ",[32,3443,3225],{"class":128},[32,3445,91],{"class":49},[32,3447,3448,3451],{"class":34,"line":179},[32,3449,3450],{"class":42},"    birthday",[32,3452,3453],{"class":49},"(u)\n",[32,3455,3456,3458,3461,3463,3465,3468,3471,3474,3476],{"class":34,"line":185},[32,3457,732],{"class":49},[32,3459,3460],{"class":42},"Printf",[32,3462,668],{"class":49},[32,3464,2448],{"class":141},[32,3466,3467],{"class":128},"%s",[32,3469,3470],{"class":141},": ",[32,3472,3473],{"class":128},"%d\\n",[32,3475,2448],{"class":141},[32,3477,3478],{"class":49},", u.Name, u.Age)\n",[32,3480,3481],{"class":34,"line":560},[32,3482,91],{"class":49},[2705,3484,3485],{"v-slot:hints":27},[2708,3486,3487,3494,3504],{},[2711,3488,3489,3490,3493],{},"Функция ",[29,3491,3492],{},"birthday"," получает копию структуры — изменения теряются",[2711,3495,3496,3497,3500,3501],{},"Передай указатель: измени сигнатуру на ",[29,3498,3499],{},"func birthday(u *User)"," и обращайся ",[29,3502,3503],{},"u.Age++",[2711,3505,3506,3507],{},"При вызове передай адрес: ",[29,3508,3509],{},"birthday(&u)",[14,3511],{},[3513,3514,3516],"h1",{"id":3515},"задачи-struct","Задачи: Struct",[14,3518],{},[10,3520,3521],{},[297,3522,3523],{},"Задача 1: Конструктор и валидация",[10,3525,3526,3529],{},[297,3527,3528],{},"Уровень:"," Лёгкая",[10,3531,3532,3535],{},[297,3533,3534],{},"Что проверяет:"," паттерн конструктора, работа со структурами",[10,3537,3538,3541,3542,3544,3545,199,3548,199,3551,3554,3555,3557,3558,3560,3561,1171],{},[297,3539,3540],{},"Условие:"," Создай структуру ",[29,3543,1431],{}," с полями ",[29,3546,3547],{},"Name string",[29,3549,3550],{},"Age int",[29,3552,3553],{},"Email string",". Напиши конструктор ",[29,3556,3037],{}," который возвращает ",[29,3559,3041],{}," и валидирует: имя не пустое, возраст от 0 до 150, email содержит ",[29,3562,3045],{},[10,3564,3565],{},[297,3566,3567],{},"Примеры:",[22,3569,3574],{"className":3570,"code":3572,"language":3573},[3571],"language-text","NewUser(\"Alice\", 30, \"alice@example.com\") → &User{...}, nil\nNewUser(\"\", 30, \"alice@example.com\")      → nil, \"name is required\"\nNewUser(\"Bob\", -1, \"bob@example.com\")     → nil, \"invalid age\"\nNewUser(\"Eve\", 25, \"not-an-email\")        → nil, \"invalid email\"\n","text",[29,3575,3572],{"__ignoreMap":27},[10,3577,3578],{},[297,3579,3580],{},"Решение:",[22,3582,3584],{"className":24,"code":3583,"language":26,"meta":27,"style":27},"package main\n\nimport (\n    \"errors\"\n    \"fmt\"\n    \"strings\"\n)\n\ntype User struct {\n    Name  string\n    Age   int\n    Email string\n}\n\nfunc NewUser(name string, age int, email string) (*User, error) {\n    if strings.TrimSpace(name) == \"\" {\n        return nil, errors.New(\"name is required\")\n    }\n    if age \u003C 0 || age > 150 {\n        return nil, errors.New(\"invalid age\")\n    }\n    if !strings.Contains(email, \"@\") {\n        return nil, errors.New(\"invalid email\")\n    }\n    return &User{Name: name, Age: age, Email: email}, nil\n}\n\nfunc main() {\n    u, err := NewUser(\"Alice\", 30, \"alice@example.com\")\n    fmt.Println(u, err)\n\n    u, err = NewUser(\"\", 30, \"alice@example.com\")\n    fmt.Println(u, err)\n}\n",[29,3585,3586,3592,3596,3602,3610,3618,3626,3630,3634,3644,3650,3656,3662,3666,3670,3706,3726,3747,3751,3777,3794,3798,3819,3836,3840,3855,3860,3865,3874,3897,3906,3911,3935,3944],{"__ignoreMap":27},[32,3587,3588,3590],{"class":34,"line":35},[32,3589,2758],{"class":38},[32,3591,2761],{"class":42},[32,3593,3594],{"class":34,"line":53},[32,3595,98],{"emptyLinePlaceholder":97},[32,3597,3598,3600],{"class":34,"line":62},[32,3599,2770],{"class":38},[32,3601,3069],{"class":49},[32,3603,3604,3606,3608],{"class":34,"line":71},[32,3605,3074],{"class":141},[32,3607,3077],{"class":42},[32,3609,2779],{"class":141},[32,3611,3612,3614,3616],{"class":34,"line":79},[32,3613,3074],{"class":141},[32,3615,2776],{"class":42},[32,3617,2779],{"class":141},[32,3619,3620,3622,3624],{"class":34,"line":88},[32,3621,3074],{"class":141},[32,3623,3094],{"class":42},[32,3625,2779],{"class":141},[32,3627,3628],{"class":34,"line":94},[32,3629,677],{"class":49},[32,3631,3632],{"class":34,"line":101},[32,3633,98],{"emptyLinePlaceholder":97},[32,3635,3636,3638,3640,3642],{"class":34,"line":108},[32,3637,39],{"class":38},[32,3639,43],{"class":42},[32,3641,46],{"class":38},[32,3643,50],{"class":49},[32,3645,3646,3648],{"class":34,"line":122},[32,3647,3119],{"class":49},[32,3649,68],{"class":38},[32,3651,3652,3654],{"class":34,"line":135},[32,3653,3126],{"class":49},[32,3655,59],{"class":38},[32,3657,3658,3660],{"class":34,"line":147},[32,3659,1310],{"class":49},[32,3661,68],{"class":38},[32,3663,3664],{"class":34,"line":158},[32,3665,91],{"class":49},[32,3667,3668],{"class":34,"line":169},[32,3669,98],{"emptyLinePlaceholder":97},[32,3671,3672,3674,3676,3678,3680,3682,3684,3686,3688,3690,3692,3694,3696,3698,3700,3702,3704],{"class":34,"line":174},[32,3673,437],{"class":38},[32,3675,3149],{"class":42},[32,3677,668],{"class":49},[32,3679,3154],{"class":443},[32,3681,674],{"class":38},[32,3683,199],{"class":49},[32,3685,3161],{"class":443},[32,3687,3164],{"class":38},[32,3689,199],{"class":49},[32,3691,3169],{"class":443},[32,3693,674],{"class":38},[32,3695,3174],{"class":49},[32,3697,3177],{"class":38},[32,3699,1431],{"class":42},[32,3701,199],{"class":49},[32,3703,3184],{"class":38},[32,3705,727],{"class":49},[32,3707,3708,3710,3713,3716,3719,3721,3724],{"class":34,"line":179},[32,3709,2415],{"class":38},[32,3711,3712],{"class":49}," strings.",[32,3714,3715],{"class":42},"TrimSpace",[32,3717,3718],{"class":49},"(name) ",[32,3720,2173],{"class":38},[32,3722,3723],{"class":141}," \"\"",[32,3725,50],{"class":49},[32,3727,3728,3731,3734,3737,3740,3742,3745],{"class":34,"line":185},[32,3729,3730],{"class":38},"        return",[32,3732,3733],{"class":128}," nil",[32,3735,3736],{"class":49},", errors.",[32,3738,3739],{"class":42},"New",[32,3741,668],{"class":49},[32,3743,3744],{"class":141},"\"name is required\"",[32,3746,677],{"class":49},[32,3748,3749],{"class":34,"line":560},[32,3750,2456],{"class":49},[32,3752,3753,3755,3758,3761,3764,3767,3769,3772,3775],{"class":34,"line":565},[32,3754,2415],{"class":38},[32,3756,3757],{"class":49}," age ",[32,3759,3760],{"class":38},"\u003C",[32,3762,3763],{"class":128}," 0",[32,3765,3766],{"class":38}," ||",[32,3768,3757],{"class":49},[32,3770,3771],{"class":38},">",[32,3773,3774],{"class":128}," 150",[32,3776,50],{"class":49},[32,3778,3779,3781,3783,3785,3787,3789,3792],{"class":34,"line":571},[32,3780,3730],{"class":38},[32,3782,3733],{"class":128},[32,3784,3736],{"class":49},[32,3786,3739],{"class":42},[32,3788,668],{"class":49},[32,3790,3791],{"class":141},"\"invalid age\"",[32,3793,677],{"class":49},[32,3795,3796],{"class":34,"line":584},[32,3797,2456],{"class":49},[32,3799,3800,3802,3805,3808,3811,3814,3817],{"class":34,"line":602},[32,3801,2415],{"class":38},[32,3803,3804],{"class":38}," !",[32,3806,3807],{"class":49},"strings.",[32,3809,3810],{"class":42},"Contains",[32,3812,3813],{"class":49},"(email, ",[32,3815,3816],{"class":141},"\"@\"",[32,3818,727],{"class":49},[32,3820,3821,3823,3825,3827,3829,3831,3834],{"class":34,"line":3247},[32,3822,3730],{"class":38},[32,3824,3733],{"class":128},[32,3826,3736],{"class":49},[32,3828,3739],{"class":42},[32,3830,668],{"class":49},[32,3832,3833],{"class":141},"\"invalid email\"",[32,3835,677],{"class":49},[32,3837,3838],{"class":34,"line":3273},[32,3839,2456],{"class":49},[32,3841,3842,3844,3847,3849,3852],{"class":34,"line":3282},[32,3843,465],{"class":38},[32,3845,3846],{"class":38}," &",[32,3848,1431],{"class":42},[32,3850,3851],{"class":49},"{Name: name, Age: age, Email: email}, ",[32,3853,3854],{"class":128},"nil\n",[32,3856,3858],{"class":34,"line":3857},26,[32,3859,91],{"class":49},[32,3861,3863],{"class":34,"line":3862},27,[32,3864,98],{"emptyLinePlaceholder":97},[32,3866,3868,3870,3872],{"class":34,"line":3867},28,[32,3869,437],{"class":38},[32,3871,2939],{"class":42},[32,3873,2047],{"class":49},[32,3875,3877,3879,3881,3883,3885,3887,3889,3891,3893,3895],{"class":34,"line":3876},29,[32,3878,3212],{"class":49},[32,3880,114],{"class":38},[32,3882,3149],{"class":42},[32,3884,668],{"class":49},[32,3886,142],{"class":141},[32,3888,199],{"class":49},[32,3890,3225],{"class":128},[32,3892,199],{"class":49},[32,3894,153],{"class":141},[32,3896,677],{"class":49},[32,3898,3900,3902,3904],{"class":34,"line":3899},30,[32,3901,732],{"class":49},[32,3903,246],{"class":42},[32,3905,3240],{"class":49},[32,3907,3909],{"class":34,"line":3908},31,[32,3910,98],{"emptyLinePlaceholder":97},[32,3912,3914,3916,3918,3920,3922,3925,3927,3929,3931,3933],{"class":34,"line":3913},32,[32,3915,3212],{"class":49},[32,3917,347],{"class":38},[32,3919,3149],{"class":42},[32,3921,668],{"class":49},[32,3923,3924],{"class":141},"\"\"",[32,3926,199],{"class":49},[32,3928,3225],{"class":128},[32,3930,199],{"class":49},[32,3932,153],{"class":141},[32,3934,677],{"class":49},[32,3936,3938,3940,3942],{"class":34,"line":3937},33,[32,3939,732],{"class":49},[32,3941,246],{"class":42},[32,3943,3240],{"class":49},[32,3945,3947],{"class":34,"line":3946},34,[32,3948,91],{"class":49},[14,3950],{},[10,3952,3953],{},[297,3954,3955],{},"Задача 2: Embedding и переопределение",[10,3957,3958,3960],{},[297,3959,3528],{}," Средняя",[10,3962,3963,3965],{},[297,3964,3534],{}," понимание embedding, переопределение методов",[10,3967,3968,3970],{},[297,3969,3540],{}," Что выведет код? Объясни поведение.",[22,3972,3974],{"className":24,"code":3973,"language":26,"meta":27,"style":27},"package main\n\nimport \"fmt\"\n\ntype Animal struct {\n    Name string\n}\n\nfunc (a Animal) Speak() string {\n    return a.Name + \" says: ...\"\n}\n\nfunc (a Animal) Describe() string {\n    return \"I am \" + a.Speak()\n}\n\ntype Dog struct {\n    Animal\n}\n\nfunc (d Dog) Speak() string {\n    return d.Name + \" says: Woof!\"\n}\n\nfunc main() {\n    d := Dog{Animal: Animal{Name: \"Rex\"}}\n    fmt.Println(d.Speak())\n    fmt.Println(d.Describe())\n    fmt.Println(d.Animal.Speak())\n}\n",[29,3975,3976,3982,3986,3996,4000,4010,4016,4020,4024,4044,4055,4059,4063,4083,4098,4102,4106,4116,4121,4125,4129,4149,4160,4164,4168,4176,4194,4206,4218,4230],{"__ignoreMap":27},[32,3977,3978,3980],{"class":34,"line":35},[32,3979,2758],{"class":38},[32,3981,2761],{"class":42},[32,3983,3984],{"class":34,"line":53},[32,3985,98],{"emptyLinePlaceholder":97},[32,3987,3988,3990,3992,3994],{"class":34,"line":62},[32,3989,2770],{"class":38},[32,3991,2773],{"class":141},[32,3993,2776],{"class":42},[32,3995,2779],{"class":141},[32,3997,3998],{"class":34,"line":71},[32,3999,98],{"emptyLinePlaceholder":97},[32,4001,4002,4004,4006,4008],{"class":34,"line":79},[32,4003,39],{"class":38},[32,4005,413],{"class":42},[32,4007,46],{"class":38},[32,4009,50],{"class":49},[32,4011,4012,4014],{"class":34,"line":88},[32,4013,422],{"class":49},[32,4015,68],{"class":38},[32,4017,4018],{"class":34,"line":94},[32,4019,91],{"class":49},[32,4021,4022],{"class":34,"line":101},[32,4023,98],{"emptyLinePlaceholder":97},[32,4025,4026,4028,4030,4032,4034,4036,4038,4040,4042],{"class":34,"line":108},[32,4027,437],{"class":38},[32,4029,440],{"class":49},[32,4031,310],{"class":443},[32,4033,446],{"class":42},[32,4035,449],{"class":49},[32,4037,452],{"class":42},[32,4039,455],{"class":49},[32,4041,458],{"class":38},[32,4043,50],{"class":49},[32,4045,4046,4048,4050,4052],{"class":34,"line":122},[32,4047,465],{"class":38},[32,4049,468],{"class":49},[32,4051,471],{"class":38},[32,4053,4054],{"class":141}," \" says: ...\"\n",[32,4056,4057],{"class":34,"line":135},[32,4058,91],{"class":49},[32,4060,4061],{"class":34,"line":147},[32,4062,98],{"emptyLinePlaceholder":97},[32,4064,4065,4067,4069,4071,4073,4075,4077,4079,4081],{"class":34,"line":158},[32,4066,437],{"class":38},[32,4068,440],{"class":49},[32,4070,310],{"class":443},[32,4072,446],{"class":42},[32,4074,449],{"class":49},[32,4076,2850],{"class":42},[32,4078,455],{"class":49},[32,4080,458],{"class":38},[32,4082,50],{"class":49},[32,4084,4085,4087,4089,4091,4093,4095],{"class":34,"line":169},[32,4086,465],{"class":38},[32,4088,2862],{"class":141},[32,4090,2865],{"class":38},[32,4092,2868],{"class":49},[32,4094,452],{"class":42},[32,4096,4097],{"class":49},"()\n",[32,4099,4100],{"class":34,"line":174},[32,4101,91],{"class":49},[32,4103,4104],{"class":34,"line":179},[32,4105,98],{"emptyLinePlaceholder":97},[32,4107,4108,4110,4112,4114],{"class":34,"line":185},[32,4109,39],{"class":38},[32,4111,489],{"class":42},[32,4113,46],{"class":38},[32,4115,50],{"class":49},[32,4117,4118],{"class":34,"line":560},[32,4119,4120],{"class":42},"    Animal\n",[32,4122,4123],{"class":34,"line":565},[32,4124,91],{"class":49},[32,4126,4127],{"class":34,"line":571},[32,4128,98],{"emptyLinePlaceholder":97},[32,4130,4131,4133,4135,4137,4139,4141,4143,4145,4147],{"class":34,"line":584},[32,4132,437],{"class":38},[32,4134,440],{"class":49},[32,4136,521],{"class":443},[32,4138,622],{"class":42},[32,4140,449],{"class":49},[32,4142,452],{"class":42},[32,4144,455],{"class":49},[32,4146,458],{"class":38},[32,4148,50],{"class":49},[32,4150,4151,4153,4155,4157],{"class":34,"line":602},[32,4152,465],{"class":38},[32,4154,2921],{"class":49},[32,4156,471],{"class":38},[32,4158,4159],{"class":141}," \" says: Woof!\"\n",[32,4161,4162],{"class":34,"line":3247},[32,4163,91],{"class":49},[32,4165,4166],{"class":34,"line":3273},[32,4167,98],{"emptyLinePlaceholder":97},[32,4169,4170,4172,4174],{"class":34,"line":3282},[32,4171,437],{"class":38},[32,4173,2939],{"class":42},[32,4175,2047],{"class":49},[32,4177,4178,4180,4182,4184,4186,4188,4190,4192],{"class":34,"line":3857},[32,4179,2946],{"class":49},[32,4181,114],{"class":38},[32,4183,489],{"class":42},[32,4185,2953],{"class":49},[32,4187,446],{"class":42},[32,4189,537],{"class":49},[32,4191,540],{"class":141},[32,4193,954],{"class":49},[32,4195,4196,4198,4200,4202,4204],{"class":34,"line":3862},[32,4197,732],{"class":49},[32,4199,246],{"class":42},[32,4201,591],{"class":49},[32,4203,452],{"class":42},[32,4205,2974],{"class":49},[32,4207,4208,4210,4212,4214,4216],{"class":34,"line":3867},[32,4209,732],{"class":49},[32,4211,246],{"class":42},[32,4213,591],{"class":49},[32,4215,2850],{"class":42},[32,4217,2974],{"class":49},[32,4219,4220,4222,4224,4226,4228],{"class":34,"line":3876},[32,4221,732],{"class":49},[32,4223,246],{"class":42},[32,4225,2995],{"class":49},[32,4227,452],{"class":42},[32,4229,2974],{"class":49},[32,4231,4232],{"class":34,"line":3899},[32,4233,91],{"class":49},[10,4235,4236],{},[297,4237,4238],{},"Ожидаемый ответ:",[22,4240,4243],{"className":4241,"code":4242,"language":3573},[3571],"Rex says: Woof!\nI am Rex says: ...\nI am Rex says: ...\n",[29,4244,4242],{"__ignoreMap":27},[10,4246,4247],{},[297,4248,3580],{},[22,4250,4252],{"className":24,"code":4251,"language":26,"meta":27,"style":27},"\u002F\u002F d.Speak() → вызывает Dog.Speak() — Dog перекрывает метод Animal.\n\n\u002F\u002F d.Describe() → Dog не определяет Describe(),\n\u002F\u002F поэтому вызывается Animal.Describe().\n\u002F\u002F Внутри Animal.Describe() вызов a.Speak() —\n\u002F\u002F это вызов на значении типа Animal, а не Dog.\n\u002F\u002F Go не знает про Dog в этом контексте — нет виртуальных методов.\n\u002F\u002F Результат: Animal.Speak(), а не Dog.Speak().\n\u002F\u002F Это ключевое отличие от наследования в ООП.\n\n\u002F\u002F d.Animal.Speak() → явный вызов Animal.Speak() напрямую.\n",[29,4253,4254,4259,4263,4268,4273,4278,4283,4288,4293,4298,4302],{"__ignoreMap":27},[32,4255,4256],{"class":34,"line":35},[32,4257,4258],{"class":104},"\u002F\u002F d.Speak() → вызывает Dog.Speak() — Dog перекрывает метод Animal.\n",[32,4260,4261],{"class":34,"line":53},[32,4262,98],{"emptyLinePlaceholder":97},[32,4264,4265],{"class":34,"line":62},[32,4266,4267],{"class":104},"\u002F\u002F d.Describe() → Dog не определяет Describe(),\n",[32,4269,4270],{"class":34,"line":71},[32,4271,4272],{"class":104},"\u002F\u002F поэтому вызывается Animal.Describe().\n",[32,4274,4275],{"class":34,"line":79},[32,4276,4277],{"class":104},"\u002F\u002F Внутри Animal.Describe() вызов a.Speak() —\n",[32,4279,4280],{"class":34,"line":88},[32,4281,4282],{"class":104},"\u002F\u002F это вызов на значении типа Animal, а не Dog.\n",[32,4284,4285],{"class":34,"line":94},[32,4286,4287],{"class":104},"\u002F\u002F Go не знает про Dog в этом контексте — нет виртуальных методов.\n",[32,4289,4290],{"class":34,"line":101},[32,4291,4292],{"class":104},"\u002F\u002F Результат: Animal.Speak(), а не Dog.Speak().\n",[32,4294,4295],{"class":34,"line":108},[32,4296,4297],{"class":104},"\u002F\u002F Это ключевое отличие от наследования в ООП.\n",[32,4299,4300],{"class":34,"line":122},[32,4301,98],{"emptyLinePlaceholder":97},[32,4303,4304],{"class":34,"line":135},[32,4305,4306],{"class":104},"\u002F\u002F d.Animal.Speak() → явный вызов Animal.Speak() напрямую.\n",[14,4308],{},[10,4310,4311],{},[297,4312,4313],{},"Задача 3: Выравнивание памяти",[10,4315,4316,4318],{},[297,4317,3528],{}," Сложная",[10,4320,4321,4323],{},[297,4322,3534],{}," понимание padding и оптимизации структур",[10,4325,4326,4328],{},[297,4327,3540],{}," Есть три структуры. Не запуская код, определи размер каждой в байтах на 64-битной платформе. Затем для каждой предложи оптимальную раскладку полей которая минимизирует размер.",[22,4330,4332],{"className":24,"code":4331,"language":26,"meta":27,"style":27},"type A struct {\n    a bool\n    b int64\n    c bool\n    d int32\n}\n\ntype B struct {\n    a int8\n    b int64\n    c int16\n    d int32\n    e bool\n}\n\ntype C struct {\n    a bool\n    b bool\n    c int64\n    d int32\n    e bool\n}\n",[29,4333,4334,4344,4351,4359,4366,4373,4377,4381,4391,4398,4404,4411,4417,4424,4428,4432,4442,4448,4454,4460,4466,4472],{"__ignoreMap":27},[32,4335,4336,4338,4340,4342],{"class":34,"line":35},[32,4337,39],{"class":38},[32,4339,862],{"class":42},[32,4341,46],{"class":38},[32,4343,50],{"class":49},[32,4345,4346,4349],{"class":34,"line":53},[32,4347,4348],{"class":49},"    a ",[32,4350,85],{"class":38},[32,4352,4353,4356],{"class":34,"line":62},[32,4354,4355],{"class":49},"    b ",[32,4357,4358],{"class":38},"int64\n",[32,4360,4361,4364],{"class":34,"line":71},[32,4362,4363],{"class":49},"    c ",[32,4365,85],{"class":38},[32,4367,4368,4370],{"class":34,"line":79},[32,4369,2946],{"class":49},[32,4371,4372],{"class":38},"int32\n",[32,4374,4375],{"class":34,"line":88},[32,4376,91],{"class":49},[32,4378,4379],{"class":34,"line":94},[32,4380,98],{"emptyLinePlaceholder":97},[32,4382,4383,4385,4387,4389],{"class":34,"line":101},[32,4384,39],{"class":38},[32,4386,880],{"class":42},[32,4388,46],{"class":38},[32,4390,50],{"class":49},[32,4392,4393,4395],{"class":34,"line":108},[32,4394,4348],{"class":49},[32,4396,4397],{"class":38},"int8\n",[32,4399,4400,4402],{"class":34,"line":122},[32,4401,4355],{"class":49},[32,4403,4358],{"class":38},[32,4405,4406,4408],{"class":34,"line":135},[32,4407,4363],{"class":49},[32,4409,4410],{"class":38},"int16\n",[32,4412,4413,4415],{"class":34,"line":147},[32,4414,2946],{"class":49},[32,4416,4372],{"class":38},[32,4418,4419,4422],{"class":34,"line":158},[32,4420,4421],{"class":49},"    e ",[32,4423,85],{"class":38},[32,4425,4426],{"class":34,"line":169},[32,4427,91],{"class":49},[32,4429,4430],{"class":34,"line":174},[32,4431,98],{"emptyLinePlaceholder":97},[32,4433,4434,4436,4438,4440],{"class":34,"line":179},[32,4435,39],{"class":38},[32,4437,899],{"class":42},[32,4439,46],{"class":38},[32,4441,50],{"class":49},[32,4443,4444,4446],{"class":34,"line":185},[32,4445,4348],{"class":49},[32,4447,85],{"class":38},[32,4449,4450,4452],{"class":34,"line":560},[32,4451,4355],{"class":49},[32,4453,85],{"class":38},[32,4455,4456,4458],{"class":34,"line":565},[32,4457,4363],{"class":49},[32,4459,4358],{"class":38},[32,4461,4462,4464],{"class":34,"line":571},[32,4463,2946],{"class":49},[32,4465,4372],{"class":38},[32,4467,4468,4470],{"class":34,"line":584},[32,4469,4421],{"class":49},[32,4471,85],{"class":38},[32,4473,4474],{"class":34,"line":602},[32,4475,91],{"class":49},[10,4477,4478,4481],{},[297,4479,4480],{},"Подсказка:"," Выравнивание поля = его размер (до 8 байт). Padding вставляется чтобы следующее поле было выровнено. Размер структуры кратен наибольшему выравниванию среди полей.",[10,4483,4484],{},[297,4485,3580],{},[22,4487,4489],{"className":24,"code":4488,"language":26,"meta":27,"style":27},"\u002F\u002F A: bool(1) + 7pad + int64(8) + bool(1) + 3pad + int32(4) = 24 байта\n\u002F\u002F Оптимально: int64(8) + int32(4) + bool(1) + bool(1) + 2pad = 16 байт\ntype AOpt struct {\n    b int64\n    d int32\n    a bool\n    c bool\n    \u002F\u002F 2 байта padding\n}\n\n\u002F\u002F B: int8(1) + 7pad + int64(8) + int16(2) + 2pad + int32(4) + bool(1) + 7pad = 32 байта\n\u002F\u002F Оптимально: int64(8) + int32(4) + int16(2) + int8(1) + bool(1) = 16 байт\ntype BOpt struct {\n    b int64\n    d int32\n    c int16\n    a int8\n    e bool\n}\n\n\u002F\u002F C: bool(1) + bool(1) + 6pad + int64(8) + int32(4) + bool(1) + 3pad = 24 байта\n\u002F\u002F Оптимально: int64(8) + int32(4) + bool(1) + bool(1) + bool(1) + 1pad = 16 байт\ntype COpt struct {\n    c int64\n    d int32\n    a bool\n    b bool\n    e bool\n    \u002F\u002F 1 байт padding\n}\n\n\u002F\u002F Проверить: unsafe.Sizeof(A{}) и т.д.\nimport \"unsafe\"\nfmt.Println(unsafe.Sizeof(A{}))    \u002F\u002F 24\nfmt.Println(unsafe.Sizeof(AOpt{})) \u002F\u002F 16\n",[29,4490,4491,4496,4501,4512,4518,4524,4530,4536,4541,4545,4549,4554,4559,4570,4576,4582,4588,4594,4600,4604,4608,4613,4618,4629,4635,4641,4647,4653,4659,4664,4668,4672,4677,4687,4706],{"__ignoreMap":27},[32,4492,4493],{"class":34,"line":35},[32,4494,4495],{"class":104},"\u002F\u002F A: bool(1) + 7pad + int64(8) + bool(1) + 3pad + int32(4) = 24 байта\n",[32,4497,4498],{"class":34,"line":53},[32,4499,4500],{"class":104},"\u002F\u002F Оптимально: int64(8) + int32(4) + bool(1) + bool(1) + 2pad = 16 байт\n",[32,4502,4503,4505,4508,4510],{"class":34,"line":62},[32,4504,39],{"class":38},[32,4506,4507],{"class":42}," AOpt",[32,4509,46],{"class":38},[32,4511,50],{"class":49},[32,4513,4514,4516],{"class":34,"line":71},[32,4515,4355],{"class":49},[32,4517,4358],{"class":38},[32,4519,4520,4522],{"class":34,"line":79},[32,4521,2946],{"class":49},[32,4523,4372],{"class":38},[32,4525,4526,4528],{"class":34,"line":88},[32,4527,4348],{"class":49},[32,4529,85],{"class":38},[32,4531,4532,4534],{"class":34,"line":94},[32,4533,4363],{"class":49},[32,4535,85],{"class":38},[32,4537,4538],{"class":34,"line":101},[32,4539,4540],{"class":104},"    \u002F\u002F 2 байта padding\n",[32,4542,4543],{"class":34,"line":108},[32,4544,91],{"class":49},[32,4546,4547],{"class":34,"line":122},[32,4548,98],{"emptyLinePlaceholder":97},[32,4550,4551],{"class":34,"line":135},[32,4552,4553],{"class":104},"\u002F\u002F B: int8(1) + 7pad + int64(8) + int16(2) + 2pad + int32(4) + bool(1) + 7pad = 32 байта\n",[32,4555,4556],{"class":34,"line":147},[32,4557,4558],{"class":104},"\u002F\u002F Оптимально: int64(8) + int32(4) + int16(2) + int8(1) + bool(1) = 16 байт\n",[32,4560,4561,4563,4566,4568],{"class":34,"line":158},[32,4562,39],{"class":38},[32,4564,4565],{"class":42}," BOpt",[32,4567,46],{"class":38},[32,4569,50],{"class":49},[32,4571,4572,4574],{"class":34,"line":169},[32,4573,4355],{"class":49},[32,4575,4358],{"class":38},[32,4577,4578,4580],{"class":34,"line":174},[32,4579,2946],{"class":49},[32,4581,4372],{"class":38},[32,4583,4584,4586],{"class":34,"line":179},[32,4585,4363],{"class":49},[32,4587,4410],{"class":38},[32,4589,4590,4592],{"class":34,"line":185},[32,4591,4348],{"class":49},[32,4593,4397],{"class":38},[32,4595,4596,4598],{"class":34,"line":560},[32,4597,4421],{"class":49},[32,4599,85],{"class":38},[32,4601,4602],{"class":34,"line":565},[32,4603,91],{"class":49},[32,4605,4606],{"class":34,"line":571},[32,4607,98],{"emptyLinePlaceholder":97},[32,4609,4610],{"class":34,"line":584},[32,4611,4612],{"class":104},"\u002F\u002F C: bool(1) + bool(1) + 6pad + int64(8) + int32(4) + bool(1) + 3pad = 24 байта\n",[32,4614,4615],{"class":34,"line":602},[32,4616,4617],{"class":104},"\u002F\u002F Оптимально: int64(8) + int32(4) + bool(1) + bool(1) + bool(1) + 1pad = 16 байт\n",[32,4619,4620,4622,4625,4627],{"class":34,"line":3247},[32,4621,39],{"class":38},[32,4623,4624],{"class":42}," COpt",[32,4626,46],{"class":38},[32,4628,50],{"class":49},[32,4630,4631,4633],{"class":34,"line":3273},[32,4632,4363],{"class":49},[32,4634,4358],{"class":38},[32,4636,4637,4639],{"class":34,"line":3282},[32,4638,2946],{"class":49},[32,4640,4372],{"class":38},[32,4642,4643,4645],{"class":34,"line":3857},[32,4644,4348],{"class":49},[32,4646,85],{"class":38},[32,4648,4649,4651],{"class":34,"line":3862},[32,4650,4355],{"class":49},[32,4652,85],{"class":38},[32,4654,4655,4657],{"class":34,"line":3867},[32,4656,4421],{"class":49},[32,4658,85],{"class":38},[32,4660,4661],{"class":34,"line":3876},[32,4662,4663],{"class":104},"    \u002F\u002F 1 байт padding\n",[32,4665,4666],{"class":34,"line":3899},[32,4667,91],{"class":49},[32,4669,4670],{"class":34,"line":3908},[32,4671,98],{"emptyLinePlaceholder":97},[32,4673,4674],{"class":34,"line":3913},[32,4675,4676],{"class":104},"\u002F\u002F Проверить: unsafe.Sizeof(A{}) и т.д.\n",[32,4678,4679,4681,4683,4685],{"class":34,"line":3937},[32,4680,2770],{"class":38},[32,4682,2773],{"class":141},[32,4684,1928],{"class":42},[32,4686,2779],{"class":141},[32,4688,4689,4691,4693,4695,4697,4699,4701,4703],{"class":34,"line":3946},[32,4690,243],{"class":49},[32,4692,246],{"class":42},[32,4694,1942],{"class":49},[32,4696,1945],{"class":42},[32,4698,668],{"class":49},[32,4700,936],{"class":42},[32,4702,1974],{"class":49},[32,4704,4705],{"class":104},"\u002F\u002F 24\n",[32,4707,4709,4711,4713,4715,4717,4719,4722,4725],{"class":34,"line":4708},35,[32,4710,243],{"class":49},[32,4712,246],{"class":42},[32,4714,1942],{"class":49},[32,4716,1945],{"class":42},[32,4718,668],{"class":49},[32,4720,4721],{"class":42},"AOpt",[32,4723,4724],{"class":49},"{})) ",[32,4726,4727],{"class":104},"\u002F\u002F 16\n",[14,4729],{},[4731,4732,4733],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}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 .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":27,"searchDepth":53,"depth":53,"links":4735},[4736,4739,4740,4745,4749,4755,4756,4757,4758],{"id":19,"depth":53,"text":20,"children":4737},[4738],{"id":218,"depth":62,"text":219},{"id":291,"depth":53,"text":292},{"id":386,"depth":53,"text":387,"children":4741},[4742,4743,4744],{"id":397,"depth":62,"text":398},{"id":639,"depth":62,"text":640},{"id":846,"depth":62,"text":847},{"id":1104,"depth":53,"text":1105,"children":4746},[4747,4748],{"id":1194,"depth":62,"text":1195},{"id":1404,"depth":62,"text":1405},{"id":1494,"depth":53,"text":1495,"children":4750},[4751,4752,4753,4754],{"id":1501,"depth":62,"text":1502},{"id":1643,"depth":62,"text":1644},{"id":1772,"depth":62,"text":1773},{"id":2001,"depth":62,"text":2002},{"id":2166,"depth":53,"text":2167},{"id":2297,"depth":53,"text":2298},{"id":2524,"depth":53,"text":2525},{"id":2694,"depth":53,"text":2695},"beginner","md",{},"basics","interfaces","\u002F01-basics\u002F04-structs",{"title":5,"description":12},"structs","01-basics\u002F04-structs\u002Findex",[2107,393,4769,4770,1518,4771,4772],"struct tags","выравнивание","zero value","собеседование","n12BdHc1Hwj7AJFwH4kUdui_OkW7olpcfj6qbuRYihk",1776291993657]