Зеҳн
Алгоритмсозӣ ва барномасозӣ дар забони Go

Китоби таълимии забони Go барои мактабиён, донишҷӯён ва омӯзгорон: аз алгоритм ва блок-схемаҳо то веб-сервер ва боти Телеграм. Таҷдиди китоби А. П. Назаров «Алгоритмсозӣ ва барномасозӣ дар забони Бейсик» (2009).

Агенти Зеҳнӣ · 26 октябри 2026 · 15 саҳифа

МаорифБарномасозӣТехнология
Аз аввал хондан

Боби 9. Функсияҳо (Зербарномаҳо)

Боби 9. Функсияҳо (Зербарномаҳо)

Ҳангоми сохтани барномаҳои калон ва мураккаб, навиштани тамоми код дар дохили як функсияи main барномаро бетартиб, печида ва нохоно мегардонад. Агар як амалиёт (масалан, ҳисоби масофаи байни ду нуқта ё тафтиши дурустии маълумот) дар чандин ҷойи барнома лозим шавад, такроран навиштани ҳамон код нигоҳдории барномаро душвор мекунад. Барои ҳалли ин масъала функсияҳо (дар забони кӯҳна — зербарномаҳо) истифода мешаванд. Дар ин боб шумо тарзи офаридани функсияҳоро дар забони Go меомӯзед.

Дар ин боб меомӯзем

  • Функсия чист ва чаро он асоси барномасозии сохторӣ мебошад.
  • Эълони функсияҳо, параметрҳо ва қимати бозгашт дар Go.
  • Баргардонидани якчанд қимат аз як функсия (multiple return values).
  • Тарзи дурусти коркарди хатоҳо (error handling) тавассути бозгашти навъи error.
  • Фарқи интиқоли додаҳо бо қимат (by value) ва бо нишондиҳанда (by pointer).
  • Ҳалли масъалаҳои мураккаби геометрӣ бо истифода аз функсияҳои ёрирасон.

Функсия чист?

Функсия — ин порчаи мустақил ва номдори кодест, ки барои ҳалли як вазифаи муайян пешбинӣ шудааст. Шумо метавонед функсияро як бор нависед ва сипас онро аз қисмҳои гуногуни барнома ҳазорҳо маротиба даъват кунед.

Дар забони кӯҳнаи Бейсик ду усули маҳдуд вуҷуд дошт:

  1. DEF FN — танҳо барои формулаҳои яксатра.
  2. GOSUB ва RETURN — ҷаҳиш ба сатри муайян, ки тамоми тағйирёбандаҳояш глобалӣ буданд ва зуд боиси хато мешуданд.

Дар Go функсияҳо метавонанд тағйирёбандаҳои маҳаллии худро дошта бошанд. Ин ба ҷудо кардани вазифаҳо ва идораи доираи дастрасии додаҳо ёрӣ медиҳад.


Сохтори эълони функсия дар Go

Намуди умумии функсия дар Go чунин аст:

func nomiFunksiya(parametr1 tip1, parametr2 tip2) naviBozgasht {
	// бадани функсия
	return natija
}

Агар якчанд параметр навъи якхела дошта бошанд, метавонем навъро танҳо дар охири онҳо як бор нависем:

func masohat(a, b float64) float64 {
	return a * b
}

Биёед як барномаи комилро бо функсияи худсохт бинем:

package main

import "fmt"

// Функсия барои ҳисоби масоҳати росткунҷа
func masohatiRostkunja(a, b float64) float64 {
	s := a * b
	return s
}

func main() {
	s1 := masohatiRostkunja(5.0, 4.0)
	s2 := masohatiRostkunja(12.5, 3.2)

	fmt.Println("Масоҳати якум:", s1)
	fmt.Println("Масоҳати дуюм:", s2)
}

Агар функсия ягон қиматро барнагардонад (танҳо чоп кунад ё амалеро иҷро намояд), навъи бозгаштро наменависем ва калимаи return шарт нест:

func salom(nom string) {
	fmt.Printf("Салом, %s! Хуш омадед!\n", nom)
}

Бозгашти якчанд қимат (Multiple Return Values)

Дар бисёр забонҳо (масалан, C ва Java) функсия бевосита танҳо як қиматро бармегардонад ва барои баргардонидани якчанд натиҷа сохторҳо ё объектҳои махсусро истифода бурдан лозим аст. Дар забони Go як функсия метавонад ду, се ва ё зиёда қиматро дар як вақт баргардонад!

Ин имконият Go-ро бениҳоят қулай ва зебо месозад.

Мисол: Функсияе, ки ҳам масоҳат ва ҳам периметри росткунҷаро якбора бармегардонад:

package main

import "fmt"

func hisobRostkunja(a, b float64) (float64, float64) {
	p := 2 * (a + b)
	s := a * b
	return p, s // бозгашти ду қимат
}

func main() {
	perimetr, masohat := hisobRostkunja(6.0, 4.0)
	fmt.Printf("Периметр: %.2f, Масоҳат: %.2f\n", perimetr, masohat)
}

Коркарди хатоҳо бо error

Дар бисёр забонҳо хатоҳо бо «истисноҳо» (exceptions, сохтори try-catch) коркард мешаванд. Go барои хатоҳои муқаррарӣ (файл ёфт нашуд, воридоти нодуруст, тақсим ба сифр) ин усулро истифода намебарад: агар ҳангоми кори функсия хатогӣ рух диҳад, функсия онро ҳамчун қимати охирини навъи error бармегардонад. (Механизми panic дар Go низ ҳаст, аммо он танҳо барои ҳолатҳои фавқулодда, масалан, хатои барномасоз, пешбинӣ шудааст.)

package main

import (
	"errors"
	"fmt"
)

// Функсияи тақсим бо санҷиши тақсим ба сифр
func taqsim(a, b float64) (float64, error) {
	if b == 0 {
		return 0, errors.New("тақсим ба сифр номумкин аст")
	}
	return a / b, nil // nil маънои набудани хатогиро дорад
}

func main() {
	natija, err := taqsim(10, 0)
	if err != nil {
		fmt.Println("Хатогӣ рух дод:", err)
		return
	}

	fmt.Println("Натиҷа:", natija)
}

Ин қоидаи тиллоии Go аст: ҳамеша санҷед, ки оё err != nil аст ё не! Дар ин сурат хатогӣ ҳеҷ гоҳ «пинҳон» намемонад ва дар ҳамон ҷое коркард мешавад, ки рух додааст.

Агар ба матни хато қимати тағйирёбандаро илова кардан лозим бошад, ба ҷойи errors.New функсияи fmt.Errorf-ро истифода баред:

return 0, fmt.Errorf("тақсими %.2f ба сифр номумкин аст", a)

Интиқол бо қимат ва бо нишондиҳанда

Дар Go ҳангоми даъвати функсия ҳар як аргумент бо қимат (by value) интиқол меёбад: функсия на худи тағйирёбанда, балки нусхаи қимати онро мегирад. Аз ин рӯ тағйири параметр дар дохили функсия ба тағйирёбандаи аслӣ таъсир намерасонад.

Агар лозим бошад, ки функсия тағйирёбандаи даъваткунандаро тағйир диҳад, ба он нишондиҳанда (pointer) — суроғаи тағйирёбанда дар хотира — фиристода мешавад. Барои ин ду аломат истифода мешаванд:

  • &x — суроғаи тағйирёбандаи x-ро медиҳад. Агар x навъи int дошта бошад, &x навъи *int («нишондиҳанда ба int») дорад.
  • *p — қимати дар суроғаи p ҷойгиршударо мехонад ё тағйир медиҳад.
package main

import "fmt"

// Параметр бо қимат: функсия нусхаи ададро мегирад
func ziyodBoQimat(n int) {
	n = n + 1 // танҳо нусха тағйир меёбад
	fmt.Println("Дар дохили функсия:", n)
}

// Параметр бо нишондиҳанда: функсия суроғаи тағйирёбандаро мегирад
func ziyodBoNishondihanda(n *int) {
	*n = *n + 1 // қимат дар ҳамон суроға тағйир меёбад
}

func main() {
	x := 10

	ziyodBoQimat(x)
	fmt.Println("Баъд аз ziyodBoQimat:", x)

	ziyodBoNishondihanda(&x)
	fmt.Println("Баъд аз ziyodBoNishondihanda:", x)

	p := &x // p — нишондиҳанда ба x (навъи *int)
	*p = 50 // тавассути p ба x қимати 50 медиҳем
	fmt.Println("Баъд аз *p = 50:", x)
}

Натиҷа:

Дар дохили функсия: 11
Баъд аз ziyodBoQimat: 10
Баъд аз ziyodBoNishondihanda: 11
Баъд аз *p = 50: 50

Мисоли классикӣ — иваз кардани қимати ду тағйирёбандаи даъваткунанда. Барои тағйир додани онҳо тавассути параметрҳо нишондиҳандаҳои онҳоро ба функсия месупорем:

func ivaz(a, b *int) {
	*a, *b = *b, *a
}

// Истифода: ivaz(&x, &y)

Қимати nil

Қимати пешфарзи ҳар як нишондиҳанда nil аст, яъне «ба ҳеҷ чиз ишора намекунад». Хондан ё навиштан тавассути нишондиҳандаи nil барномаро бо хатои фавқулодда (panic: nil pointer dereference) қатъ мекунад, бинобар ин агар нишондиҳанда метавонад холӣ бошад, онро пешакӣ санҷед:

var q *int // q == nil
if q == nil {
	fmt.Println("q ба ҳеҷ тағйирёбанда ишора намекунад")
} else {
	fmt.Println(*q)
}

Буришҳо ҳамчун параметр

Буриш низ бо қимат интиқол меёбад, вале чунон ки дар боби 7 дидем, нусхаи буриш ба ҳамон массиви зеринӣ ишора мекунад. Аз ин рӯ функсия метавонад унсурҳои буришро тағйир диҳад (масалан, a[0] = 0 дар дохили функсия дар буриши аслӣ низ дида мешавад), аммо агар дар дохили функсия append кунад, дарозии буриши даъваткунанда тағйир намеёбад. Барои ҳамин функсияҳое, ки буришро дароз мекунанд, буриши навро бармегардонанд — монанди худи append.

Дар боби 10 мо нишондиҳандаҳоро барои тағйир додани сохторҳо (struct) ва дар методҳо истифода хоҳем бурд.


Масъалаи амалӣ: Ёфтани медианаҳои секунҷа

Дар китоби кӯҳнаи Бейсик (§34) масъалаи зерин оварда шудааст:

Координатаҳои қуллаҳои секунҷаи ABC маълуманд: A(x₁, y₁), B(x₂, y₂) ва C(x₃, y₃). Дарозии медианаҳои секунҷаро ёбед.

Дар китоби кӯҳна ин масъала бо сатрҳои печида ва рамзгузориҳои FND ва FNP иҷро шуда буд. Биёед бубинем, ки бо функсияҳои муосири Go ин масъала то чӣ андоза равшан ва зебо ҳал мешавад:

package main

import (
	"fmt"
	"math"
)

// Масофаи байни ду нуқта: d = sqrt((x1-x2)^2 + (y1-y2)^2)
func masofa(x1, y1, x2, y2 float64) float64 {
	dx := x1 - x2
	dy := y1 - y2
	return math.Sqrt(dx*dx + dy*dy)
}

// Координатаи миёнаҷои порча
func miyona(c1, c2 float64) float64 {
	return (c1 + c2) / 2.0
}

func main() {
	// Координатаҳои қуллаҳои секунҷа
	x1, y1 := 0.0, 0.0 // Нуқтаи A
	x2, y2 := 6.0, 0.0 // Нуқтаи B
	x3, y3 := 0.0, 8.0 // Нуқтаи C

	// 1. Ёфтани миёнаҷои тарафҳо:
	// Миёнаҷои тарафи BC (барои медианаи A)
	mAx := miyona(x2, x3)
	mAy := miyona(y2, y3)

	// Миёнаҷои тарафи AC (барои медианаи B)
	mBx := miyona(x1, x3)
	mBy := miyona(y1, y3)

	// Миёнаҷои тарафи AB (барои медианаи C)
	mCx := miyona(x1, x2)
	mCy := miyona(y1, y2)

	// 2. Ҳисоби дарозии медианаҳо
	medianaA := masofa(x1, y1, mAx, mAy)
	medianaB := masofa(x2, y2, mBx, mBy)
	medianaC := masofa(x3, y3, mCx, mCy)

	fmt.Println("======== ДАРОЗИИ МЕДИАНАҲО ========")
	fmt.Printf("Медиана аз қуллаи A: %.2f\n", medianaA)
	fmt.Printf("Медиана аз қуллаи B: %.2f\n", medianaB)
	fmt.Printf("Медиана аз қуллаи C: %.2f\n", medianaC)
}

Худатон бисанҷед

9–1. Ҳисоби дараҷа: Функсияе бо номи daraja(asos float64, n int) float64 нависед, ки бе истифодаи бастаи math асосро ба дараҷаи бутуни n бо ёрии даври for бардорад. Ҳолати n < 0-ро низ ба назар гиред (a⁻ⁿ = 1 / aⁿ).

9–2. Калонтарин ва хурдтарин бо як функсия: Функсияе бо номи minMax(massiv []int) (int, int) нависед, ки буриши ғайрихолии ададҳоро қабул карда, хурдтарин ва калонтарин адади онро баргардонад.

9–3. Ҳалли муодилаи хаттӣ бо коркарди хато: Функсияе созед, ки муодилаи хаттии ax + b = 0-ро ҳал намояд: func halKhatti(a, b float64) (float64, error). Агар a = 0 ва b ≠ 0 бошад, хатои «ҳал надорад»-ро баргардонед. Агар a = 0 ва b = 0 бошад, бо хатои ҷудогона хабар диҳед, ки муодила беохир бисёр ҳал дорад.

9–4. Баландиҳои секунҷа: Бо истифода аз функсияҳои сохтаамон баландиҳои секунҷаеро, ки қуллаҳояш A(x₁, y₁), B(x₂, y₂), C(x₃, y₃) мебошанд, ҳисоб кунед (масоҳати секунҷа тавассути формулаи Герон ёфта шуда, баландиҳо бо формулаи hₐ = 2S / a ёфта мешаванд).


Хулоса

Дар ин боб шумо фаҳмидед, ки чӣ тавр барномаҳои калонро ба функсияҳои хурд ва хоно тақсим кунед. Шумо тарзи эълони параметрҳо ва қимати бозгаштро дар Go омӯхтед, бо хусусияти барҷастаи бозгашти якчанд қимат шинос шудед, фарқи интиқол бо қимат ва бо нишондиҳандаро (&, *, nil) дидед ва фаҳмидед, ки чаро коркарди хатоҳо бо error барномаҳои Go-ро ин қадар устувор ва боэътимод мегардонад.

Дар боби 10 мо ба сохторҳо (struct) ва харитаҳо (map) мегузарем, ки ба мо имкон медиҳанд маълумоти мураккаби ҷаҳони воқеиро муттаҳид намоем.

пешина
аз 15
навбатӣ