انواع داده در گولنگ - آموزش متغیرها و تایپها در Go
2025/11/24درک انواع داده یکی از اساسیترین مفاهیم در هر زبان برنامهنویسی است. Go یک زبان strongly typed است، یعنی هر متغیر باید نوع مشخصی داشته باشد. در این مقاله، تمام انواع داده در Go را با مثالهای عملی بررسی میکنیم.
تعریف متغیر در Go
قبل از بررسی انواع داده، باید با روشهای تعریف متغیر آشنا شویم:
روش ۱: تعریف کامل با var
var name string = "علی"
var age int = 25
var price float64 = 19.99
var isActive bool = trueروش ۲: استنتاج نوع (Type Inference)
var name = "علی" // Go خودش تشخیص میدهد: string
var age = 25 // int
var price = 19.99 // float64روش ۳: تعریف کوتاه با :=
name := "علی" // فقط داخل توابع کار میکند
age := 25
price := 19.99روش ۴: تعریف چندگانه
var (
name string = "علی"
age int = 25
isAdmin bool = false
)
// یا
x, y, z := 1, 2, 3انواع داده پایه (Basic Types)
۱. اعداد صحیح (Integers)
Go انواع مختلفی از اعداد صحیح دارد:
| نوع | اندازه | محدوده |
|---|---|---|
int8 |
8 بیت | -128 تا 127 |
int16 |
16 بیت | -32,768 تا 32,767 |
int32 |
32 بیت | -2.1 میلیارد تا 2.1 میلیارد |
int64 |
64 بیت | -9.2 کوینتیلیون تا 9.2 کوینتیلیون |
int |
32 یا 64 بیت | بستگی به سیستم |
اعداد صحیح بدون علامت (Unsigned):
| نوع | اندازه | محدوده |
|---|---|---|
uint8 (byte) |
8 بیت | 0 تا 255 |
uint16 |
16 بیت | 0 تا 65,535 |
uint32 |
32 بیت | 0 تا 4.2 میلیارد |
uint64 |
64 بیت | 0 تا 18.4 کوینتیلیون |
package main
import "fmt"
func main() {
var a int = 42
var b int8 = 127
var c uint = 100
var d byte = 255 // معادل uint8
fmt.Printf("a: %d (type: %T)\n", a, a)
fmt.Printf("b: %d (type: %T)\n", b, b)
fmt.Printf("c: %d (type: %T)\n", c, c)
fmt.Printf("d: %d (type: %T)\n", d, d)
}نکته: در بیشتر موارد از int استفاده کنید. فقط وقتی به بهینهسازی حافظه نیاز دارید، نوع دقیق را مشخص کنید.
۲. اعداد اعشاری (Floating Point)
| نوع | اندازه | دقت |
|---|---|---|
float32 |
32 بیت | ~7 رقم اعشار |
float64 |
64 بیت | ~15 رقم اعشار |
package main
import (
"fmt"
"math"
)
func main() {
var pi float64 = 3.14159265358979
var e float32 = 2.71828
fmt.Printf("pi = %.10f\n", pi)
fmt.Printf("e = %.5f\n", e)
// اعداد خاص
inf := math.Inf(1) // بینهایت مثبت
nan := math.NaN() // Not a Number
fmt.Printf("Infinity: %f\n", inf)
fmt.Printf("NaN: %f\n", nan)
}نکته: همیشه از float64 استفاده کنید مگر اینکه دلیل خاصی برای float32 داشته باشید.
۳. اعداد مختلط (Complex Numbers)
var c1 complex64 = 3 + 4i
var c2 complex128 = complex(5, 12)
fmt.Println(c1) // (3+4i)
fmt.Println(real(c2)) // 5
fmt.Println(imag(c2)) // 12۴. بولین (Boolean)
var isActive bool = true
var isAdmin bool = false
// عملگرهای منطقی
fmt.Println(true && false) // false (AND)
fmt.Println(true || false) // true (OR)
fmt.Println(!true) // false (NOT)
// مقایسه
x, y := 5, 10
fmt.Println(x < y) // true
fmt.Println(x == y) // false
fmt.Println(x != y) // true۵. رشته (String)
رشتهها در Go immutable هستند، یعنی پس از ایجاد قابل تغییر نیستند.
package main
import (
"fmt"
"strings"
)
func main() {
// تعریف رشته
name := "سلام دنیا"
greeting := `این یک
رشته چند خطی
است`
// طول رشته (تعداد بایت)
fmt.Println(len(name)) // 17 (UTF-8 bytes)
// تعداد کاراکترها
fmt.Println(len([]rune(name))) // 9
// الحاق رشته
fullName := "علی" + " " + "رضایی"
fmt.Println(fullName)
// توابع کاربردی
s := "Hello, World!"
fmt.Println(strings.ToUpper(s)) // HELLO, WORLD!
fmt.Println(strings.ToLower(s)) // hello, world!
fmt.Println(strings.Contains(s, "World")) // true
fmt.Println(strings.Replace(s, "World", "Go", 1))
fmt.Println(strings.Split(s, ", ")) // [Hello World!]
}۶. Rune
rune معادل int32 است و برای نمایش یک کاراکتر Unicode استفاده میشود:
package main
import "fmt"
func main() {
var r rune = 'ا' // حرف الف فارسی
fmt.Printf("%c = %d\n", r, r) // ا = 1575
// پیمایش روی رشته فارسی
text := "سلام"
for i, char := range text {
fmt.Printf("Index: %d, Char: %c, Code: %d\n", i, char, char)
}
}انواع داده مرکب (Composite Types)
۱. آرایه (Array)
آرایهها طول ثابت دارند و نوع عناصر یکسان است:
package main
import "fmt"
func main() {
// تعریف آرایه
var numbers [5]int // [0 0 0 0 0]
var names [3]string = [3]string{"علی", "رضا", "مریم"}
scores := [4]int{90, 85, 78, 92}
auto := [...]int{1, 2, 3, 4, 5} // طول خودکار
// دسترسی و تغییر
numbers[0] = 10
fmt.Println(numbers[0]) // 10
// طول آرایه
fmt.Println(len(scores)) // 4
// پیمایش
for i, name := range names {
fmt.Printf("%d: %s\n", i, name)
}
// آرایه دو بعدی
matrix := [2][3]int{
{1, 2, 3},
{4, 5, 6},
}
fmt.Println(matrix[1][2]) // 6
}۲. برش (Slice)
Sliceها آرایههای پویا هستند و بیشترین استفاده را دارند:
package main
import "fmt"
func main() {
// ایجاد slice
var s1 []int // nil slice
s2 := []int{1, 2, 3, 4, 5} // با مقدار اولیه
s3 := make([]int, 5) // طول 5، ظرفیت 5
s4 := make([]int, 3, 10) // طول 3، ظرفیت 10
fmt.Printf("s1: %v, len=%d, cap=%d\n", s1, len(s1), cap(s1))
fmt.Printf("s2: %v, len=%d, cap=%d\n", s2, len(s2), cap(s2))
// اضافه کردن عنصر
s1 = append(s1, 1, 2, 3)
fmt.Println(s1) // [1 2 3]
// برش از slice
sub := s2[1:4] // [2 3 4]
fmt.Println(sub)
// کپی
dst := make([]int, len(s2))
copy(dst, s2)
// حذف عنصر (ایندکس 2)
s2 = append(s2[:2], s2[3:]...)
fmt.Println(s2) // [1 2 4 5]
}۳. نقشه (Map)
Mapها ساختار داده کلید-مقدار هستند:
package main
import "fmt"
func main() {
// ایجاد map
var m1 map[string]int // nil map
m2 := map[string]int{"علی": 25, "رضا": 30} // با مقدار
m3 := make(map[string]int) // خالی
// اضافه کردن
m3["مریم"] = 28
m3["زهرا"] = 22
// دسترسی
age := m2["علی"]
fmt.Println(age) // 25
// بررسی وجود کلید
value, exists := m2["حسن"]
if exists {
fmt.Println(value)
} else {
fmt.Println("کلید وجود ندارد")
}
// حذف
delete(m2, "علی")
// پیمایش
for key, value := range m3 {
fmt.Printf("%s: %d\n", key, value)
}
// طول
fmt.Println(len(m3))
}۴. ساختار (Struct)
Structها برای گروهبندی دادههای مرتبط استفاده میشوند:
package main
import "fmt"
// تعریف struct
type Person struct {
Name string
Age int
Email string
IsAdmin bool
}
// struct تو در تو
type Company struct {
Name string
CEO Person
Employees []Person
}
func main() {
// ایجاد نمونه
p1 := Person{
Name: "علی رضایی",
Age: 30,
Email: "ali@example.com",
IsAdmin: true,
}
// دسترسی به فیلدها
fmt.Println(p1.Name)
p1.Age = 31
// ایجاد با ترتیب
p2 := Person{"رضا", 25, "reza@example.com", false}
// اشارهگر به struct
p3 := &Person{Name: "مریم", Age: 28}
fmt.Println(p3.Name) // نیازی به *p3.Name نیست
// struct ناشناس
point := struct {
X, Y int
}{10, 20}
fmt.Println(point)
// struct تو در تو
company := Company{
Name: "شرکت نمونه",
CEO: p1,
Employees: []Person{p2},
}
fmt.Println(company.CEO.Name)
}تبدیل نوع (Type Conversion)
Go تبدیل خودکار نوع ندارد و باید صریحاً انجام شود:
package main
import (
"fmt"
"strconv"
)
func main() {
// عدد به عدد
var i int = 42
var f float64 = float64(i)
var u uint = uint(i)
fmt.Printf("int: %d, float64: %f, uint: %d\n", i, f, u)
// عدد به رشته
s1 := strconv.Itoa(42) // "42"
s2 := fmt.Sprintf("%d", 42) // "42"
s3 := strconv.FormatFloat(3.14, 'f', 2, 64) // "3.14"
fmt.Println(s1, s2, s3)
// رشته به عدد
n1, _ := strconv.Atoi("42") // 42
n2, _ := strconv.ParseFloat("3.14", 64) // 3.14
n3, _ := strconv.ParseBool("true") // true
fmt.Println(n1, n2, n3)
// رشته به بایت و برعکس
bytes := []byte("سلام")
str := string(bytes)
fmt.Println(str)
}مقدار صفر (Zero Value)
در Go، متغیرهای تعریفشده بدون مقدار اولیه، مقدار صفر میگیرند:
| نوع | مقدار صفر |
|---|---|
int, float |
0 |
bool |
false |
string |
"" (رشته خالی) |
pointer, slice, map, channel, func |
nil |
var i int // 0
var f float64 // 0.0
var b bool // false
var s string // ""
var p *int // nil
var sl []int // nil
var m map[string]int // nilType Alias و Type Definition
// Type Definition - نوع جدید
type UserID int
type Username string
// Type Alias - فقط نام جدید
type ID = int
func main() {
var uid UserID = 100
var id ID = 100
// uid و int تایپ متفاوت هستند
// var x int = uid // خطا!
var x int = int(uid) // درست
// id و int یکی هستند
var y int = id // درست
}جمعبندی
| دسته | انواع | کاربرد |
|---|---|---|
| اعداد صحیح | int, int8-64, uint, uint8-64 |
شمارش، ایندکس |
| اعداد اعشاری | float32, float64 |
محاسبات علمی، قیمت |
| بولین | bool |
شرطها، فلگها |
| رشته | string |
متن، دادههای متنی |
| آرایه | [n]T |
داده با طول ثابت |
| Slice | []T |
لیستهای پویا |
| Map | map[K]V |
جستجوی سریع |
| Struct | struct{} |
دادههای ساختاریافته |