Go тілі: нөлден өз блогыңызға дейін 5-сабақ (барлығы 50)
Go-дағы функциялар: параметрлер, return және екі мән
Go курсының бесінші сабағы. Функцияны қалай жариялау керек және параметр, аргумент, return деген не. Сабақтың ең бастысы: Go-да функция бірден екі мән қайтарады — нәтиже және шықты ма деген белгі. Тілде ерекше жағдайлардың жоқтығы содан. result, ok := тәсілін талдаймыз.
Не үшін керек
Бағдарлама өседі, бір әрекеттер қайталана бастайды. Функция — аты бар, жазып қойылған әрекеттер реті: бір рет жазасыз да, қалағаныңызша шақырасыз.
Бірақ сабақтың ең бастысы — басқа нәрсе. Go-да функция бірден екі нәрсе қайтара алады: нәтижені және шықты ма деген белгіні. Тілдегі қателермен жұмыстың бәрі соған негізделген: Go-да try/catch тәрізді ерекше жағдайларды ұстау тетігі жоқ, қате — кәдімгі қайтарылатын мән. Шынымен ерекше жағдайларға арналған тетік (panic) бар, бірақ ол бұл үшін емес.
Бірден тұтас
Жаңа қалта, go mod init sabaq04, main.go:
package main
import "fmt"
func greet(name string) string {
return "Сәлем, " + name + "!"
}
func divide(a, b float64) (float64, bool) {
if b == 0 {
return 0, false
}
return a / b, true
}
func main() {
fmt.Println(greet("әлем"))
result, ok := divide(10, 4)
fmt.Println("10 / 4 =", result, "· шықты:", ok)
result, ok = divide(10, 0)
fmt.Println("10 / 0 =", result, "· шықты:", ok)
}
Іске қоспас бұрын — төменге қарамай, оның не басып шығаратынын дауыстап айтыңыз. Содан кейін жіберіп, салыстырыңыз: айырма шыққан жер — тілді әлі білмейтін тұсыңыз.
go run . мынаны басады:
Сәлем, әлем!
10 / 4 = 2.5 · шықты: true
10 / 0 = 0 · шықты: false
Соңғы жолға назар аударыңыз. Жалған әсер қалмас үшін бірден нақтылайық: Go біздің тексеруіміз болмаса да құламас еді. Go-да float64-ті нөлге бөлу апат емес — ол +Inf, -Inf не NaN береді. Тексеру бағдарламаны құтқару үшін емес, әрі қарай мағынасыз санды жібермеу үшін керек: +Inf бетке дейін тып-тыныш жетіп, оқырманға көрінеді.
Талдау
Жариялау қалай оқылады
func greet(name string) string {
Солдан оңға: func — функция басталады; greet — оның аты; (name string) — не әкелу керек және ол ішінде қалай аталады; жақшадан кейінгі string — шығуда не болатыны.
Елестетіп көріңіз. Шеберханадағы тапсырыс бланкісі. Жоғарыда «не әкелесіз» деген жол, төменде «нені аласыз» деген жол. Бланк толтырылып, тапсырылмайынша шебер ештеңе істемейді.
Параметр мен аргумент
Бұл екі бөлек сөз, оларды үнемі шатастырады.
Параметр — жариялаудағы name. Бұл болашақ мәнге дайындалған бос орын.
Аргумент — greet("әлем") шақыруындағы "әлем". Бұл — сол орынға салғаныңыз.
Елестетіп көріңіз. Бланктегі жол және сіз оған жазған нәрсе. Жол әрқашан сол күйінде, ал оған әр жолы басқа нәрсе жазылады.
return
return функцияның жұмысын аяқтап, нәтижені сыртқа береді. Одан кейін жазылғанның бәрі орындалмайды.
Елестетіп көріңіз. Дайынды беру терезесіне тапсырып, тапсырысты жабу. Бергеннен кейін шебер бұл тапсырысқа қайтып оралмайды, дәптерде төменде жазу қалса да.
Ерекше жағдайлардың орнына екі мән
Сабақтың ең басты орны:
func divide(a, b float64) (float64, bool) {
Екі типтің айналасындағы дөңгелек жақша: функция бірден екі нәрсе береді. Біріншісі — бөлудің нәтижесі, екіншісі — шықты ма.
Неге олай. Нөлге бөлу — бағдарламаның бұзылуы емес, алдын ала қарастыру керек қалыпты жағдай. Басқа тілдерде мұндайды бөлек тетікпен «лақтырады», ал оны ұстамай қалу оңай. Go сәтсіздікті шетке жасырмай, тікелей қолыңызға екінші мән етіп береді.
Елестетіп көріңіз. Терезеден берілген анықтама. Сізге қағазды ғана емес, «берілді» немесе «бас тартылды» деген белгіні де береді. Бірінсіз екіншісі берілмейді — белгі анықтамамен бірге қолыңызға тиеді, оны көрмеу үшін әдейі теріс айналу керек. Төменде мұның кодта қалай көрінетінін қараймыз.
Екі мәнді қалай қабылдау
:= сол жағында үтір арқылы екі ат жазылады:
result, ok := divide(10, 4)
Реті маңызды: бірінші нәтиже, екінші белгі. Аттарды өзіңіз таңдайсыз, компилятор оларды тексермейді: ok, result := divide(10, 4) деп жазсаңыз да жиналады, тек ok ішінде сан, result ішінде иә-жоқ болады. Мағынаны ат емес, рет береді.
Екінші атты әрдайым дерлік ok деп атайды, ал нағыз қателер туралы болғанда — err. Бұл тілдің ережесі емес, ортақ әдет, соның арқасында бөгде код бірден оқылады.
Екінші мән керек болмаса
Оны жай тастап кетуге болмайды: Go функция қайтарғанның бәрін қабылдауды талап етеді. «Маған бұл керек емес» дегеннің белгісі — астыңғы сызық:
result, _ := divide(10, 4)
Елестетіп көріңіз. Бланктегі сызып тастаған жол. Бос қалдыруға болмайды — бланкті қабылдамайды. Ал сызып тастауға болады: жолды байқап, әдейі өткізіп жібергені көрініп тұр.
ok дегенді олай тастау дұрыс емес: бірдеңе дұрыс кетпегені туралы жалғыз хабарды өз қолыңызбен лақтырып жіберген боласыз.
Типі бірдей бірнеше параметр
func divide(a, b float64) (float64, bool)
a мен b екеуі де float64, тип соңында бір рет жазылған. Типтері әртүрлі болса — әрқайсысына жазылады: func post(title string, views int).
Функция қайтаратын функция
Go-да функция — сан немесе жол сияқты мән. Оны айнымалыға салуға, параметр етіп беруге және басқа функциядан қайтаруға болады. Соңғысы үйреншікті емес көрінеді, бірақ осы курста-ақ кездеседі, сондықтан қазір қарайық:
func counter() func() int {
n := 0
return func() int {
n = n + 1
return n
}
}
func main() {
next := counter()
fmt.Println(next())
fmt.Println(next())
fmt.Println(next())
other := counter()
fmt.Println("басқа санауыш:", other())
}
1
2
3
басқа санауыш: 1
Жариялау бұрынғыдай оқылады: func counter() — параметрсіз функция, ал оның қайтару типі — func() int, яғни «параметрсіз, бүтін сан қайтаратын функция».
Енді ең бастысы. n counter ішінде жарияланған, әрі бұрынғы ережелер бойынша counter аяқталғанда жоғалуға тиіс еді. Бірақ ол тірі: қайтарылған функция оны есінде ұстайды әрі әр шақыруда өзгертеді. Мұндай функцияны тұйықталу (closure) деп атайды — ол өзі туған функциядағы айнымалыны өзіне тұйықтап алған.
Шығудың соңғы жолы — бұл бәріне ортақ айнымалы емес екенінің дәлелі: екінші санауыштың өз n-і бар, ол бірден бастайды.
Елестетіп көріңіз. Қалтадағы қағаз. Функция туған үйінен кетті, бірақ саны жазылған парақты өзімен бірге алып шықты — әрі бөтендікін емес, дәл өз парағын түзетеді.
Жазудан қорықпаңыз, оны жиі көресіз. Орама туралы сабақта өңдеушіні алып, жаңасын қайтаратын функция жазасыз — ол дәл осылай құрылған, ал ондағы n-нің орнын орама есінде ұстауға тиіс нәрсе басады.
Сабақ картасы
Өз сөзіңізбен айтыңыз
Қарамай, дауыстап немесе қағазға жазып жауап беріңіз. Жауаптары — сабақтың соңында.
- Параметр мен аргументтің айырмашылығы неде?
divideнеге нөлге бөлгенде бағдарламаны тоқтатпай,boolқайтарады?- Сол жағында бір ат тұрған
result := divide(10, 4)деп жазсаңыз не болады?
Тапсырма
Міндетті. readingTime(words int) int функциясын жазыңыз — минутына 200 сөз есебімен оқу уақытын жоғарыға дөңгелектеп қайтарады: (words + 199) / 200. Бүтін бөлу қалдықты тастайды, сондықтан 199-ды бөлудің алдында қосады: толымсыз минут сонда да есепке кіреді, ал тура 400 сөз 3 емес, 2 береді. Функцияны main ішінен 150, 400 және 1000 сөз үшін шақырып, жауаптарын салыстырыңыз: 1, 2 және 5 шығуы керек. Нөл сөздің оқу уақыты — нөл, бұл дұрыс.
Қалауыңызша.
readingTimeекі мән қайтаратын етіңіз: минут жәнеbool— сөз саны орынды ма. Тексеру үшінifкерек, оны келесі сабақта талдаймыз: әзірге шықпаса, содан кейін оралыңыз.divide(10, 0)шақыруындаokорнына_қойып, бағдарламаның не басатынын көріңіз. Қателер дәл осылай жоғалады.returnжоқ, ал жариялауда нәтиже типі бар функция жазыңыз. Go не айтатынын оқыңыз.
Блогта қайда тұрады
Блогыңыздағы көп функция екі мән қайтарады: мақала және «табылды ма», мәтін және «талдау сәтті ме», дерекқорға қосылым және «қосылды ма». Қателер туралы сабақта екінші мән bool емес, error болады — Go-ның нағыз жұмыс тәсілі сол.
Жауаптар
Жауаптарды көрсету
- Параметр — функция жариялауындағы ат, мәнге арналған бос орын. Аргумент — шақырғанда қойған нақты мән. Параметр әрқашан сол күйінде, аргумент әр жолы басқа.
- Себебі мұнда нөлге бөлу — апат емес: Go
+Infқайтарып, әрі қарай жүре берер еді. Қауіптісі де сол — мағынасыз сан бағдарлама бойымен үнсіз тарайды. Белгі қайтара отырып, функция жауап алынғандай сыңай танытпай, шешімді өзін шақырғанға береді. - Бағдарлама жиналмайды. Go шамамен
assignment mismatch: 1 variable but divide returns 2 valuesдейді: тіл қайтарылған мәнді үнсіз жоғалтуға жол бермейді, одан бас тарту үшін астыңғы сызық бар.
Пікірлер (0)
Пікір қалдыру үшін кіріңіз →
Әзірге пікір жоқ. Бірінші болыңыз.