1 การทำความเข้าใจเกี่ยวกับประเภทข้อมูลของภาษา Go

ใน ภาษา Go, ประเภทข้อมูลเป็นพื้นฐานของการเขียนโปรแกรม และกำหนดรูปแบบของข้อมูลที่ตัวแปรสามารถเก็บไว้ได้ ประเภทข้อมูลพื้นฐานที่ภาษา Go มีคือ

ประเภทข้อมูล คำอธิบาย การใช้งานหน่วยความจำ
bool ประเภทบูลีน, ใช้เก็บค่า true หรือ false 1 ไบต์
int, uint จำนวนเต็มและจำนวนเต็มบวก, ขนาดเริ่มต้นขึ้นอยู่กับแพลตฟอร์มระบบ 4 หรือ 8 ไบต์
int8, uint8 จำนวนเต็ม 8 บิตและจำนวนเต็มบวก 8 บิต 1 ไบต์
int16, uint16 จำนวนเต็ม 16 บิตและจำนวนเต็มบวก 16 บิต 2 ไบต์
int32, uint32 จำนวนเต็ม 32 บิตและจำนวนเต็มบวก 32 บิต 4 ไบต์
int64, uint64 จำนวนเต็ม 64 บิตและจำนวนเต็มบวก 64 บิต 8 ไบต์
float32 จำนวนทศนิยม 32 บิต 4 ไบต์
float64 จำนวนทศนิยม 64 บิต 8 ไบต์
complex64 จำนวนเชิงซ้อนที่มีส่วนจริงและส่วนจินตภาพ 32 บิต 8 ไบต์
complex128 จำนวนเชิงซ้อนที่มีส่วนจริงและส่วนจินตภาพ 64 บิต 16 ไบต์
byte คล้ายกับ uint8 1 ไบต์
rune คล้ายกับ int32 แทนรหัส Unicode 4 ไบต์
string ประเภทข้อมูลสตริง ขึ้นอยู่กับความยาวของสตริง
error อินเตอร์เฟซข้อผิดพลาด, ใช้สำหรับส่งค่าข้อผิดพลาด ไม่มีขนาดคงที่

ประเภทเหล่านี้สามารถถูกเลือกตามความต้องการต่าง ๆ เช่น การคำนวณตัวเลข, การประมวลผลข้อความ, หรือควบคุมตรรกะทางตรรกะ

2 ประเภทข้อมูลจำนวนเต็ม

2.1 ภาพรวมของประเภทข้อมูลจำนวนเต็ม

ภาษา Go มีประเภทข้อมูลจำนวนเต็มที่สร้างมาให้ใช้หลากหลายประเภทดังนี้:

  • จำนวนเต็มที่ลงชื่อ: int8, int16, int32 (หรือ rune), int64, และ int
  • จำนวนเต็มบวก: uint8 (หรือ byte), uint16, uint32, uint64, และ uint

ขนาดของ int และ uint คือ 4 ไบต์บนระบบ 32 บิต และ 8 ไบต์บนระบบ 64 บิต ช่วงค่าของประเภทข้อมูลจำนวนเต็มแสดงในตารางด้านล่าง:

ประเภท ช่วงของค่า
int8 -128 ถึง 127
uint8 0 ถึง 255
int16 -32768 ถึง 32767
uint16 0 ถึง 65535
int32 -2147483648 ถึง 2147483647
uint32 0 ถึง 4294967295
int64 -9223372036854775808 ถึง 9223372036854775807
uint64 0 ถึง 18446744073709551615

2.2 การใช้งานตัวแปรจำนวนเต็ม

รูปแบบพื้นฐานในการประกาศตัวแปรจำนวนเต็มคือดังนี้:

var ชื่อตัวแปร ประเภทข้อมูล = ค่าเริ่มต้น

ตัวอย่างโค้ด:

package main
import "fmt"

func main() {
    var a int = 10 // ตัวแปรจำนวนเต็มและลงชื่อ
    var b uint = 20 // ตัวแปรจำนวนเต็มบวก
    var c int8 = -128 // ค่า int8 ที่เล็กที่สุด
    fmt.Println(a, b, c)
}

2.3 การดำเนินการทางคณิตศาสตร์ของจำนวนเต็ม

ภาษา Go รองรับตัวดำเนินการทางคณิตศาสตร์ทั่วไป เช่น การบวก (+), การลบ (-), การคูณ (*), การหาร (/), และโมดูลัส (%), ไปจนถึงตัวดำเนินการแบบวิตวี เช่น วิตวี AND (&), OR (|), XOR (^), การสเลิกซ้าย (<<), และการสเลิกขวา (>>).

package main
import "fmt"

func main() {
    x := 10
    y := 3

    // ดำเนินการทางคณิตศาสตร์
    fmt.Println(x + y) // การบวก
    fmt.Println(x - y) // การลบ
    fmt.Println(x * y) // การคูณ
    fmt.Println(x / y) // การหาร
    fmt.Println(x % y) // โมดูลัส

    // ดำเนินการทางวิตวี
    fmt.Println(x & y)  // วิตวี AND
    fmt.Println(x | y)  // วิตวี OR
    fmt.Println(x ^ y)  // วิตวี XOR
    fmt.Println(x << 1) // การเลิกซ้ายทีละ 1
    fmt.Println(x >> 1) // การเลิกขวาทีละ 1
}

3 ประเภทข้อมูลทศนิยมทวิภาค

3.1 ภาพรวมของประเภทข้อมูลจำนวนจริง (Floating Point)

ในภาษา Go, ประเภทข้อมูลที่เป็นจำนวนจริงรวมถึง float32 และ float64 ซึ่งสอดคล้องกับข้อมูลจริงที่มีขนาด 32 บิตและ 64 บิต โดยทั่วไปแล้วแนะนำให้ใช้ float64 เนื่องจากมีช่วงค่าที่กว้างกว่า และมีความแม่นยำมากขึ้น

  • float32 ประมาณ 23 บิตที่สำคัญ มีประมาณ 7 หลักทศนิยม
  • float64 ประมาณ 52 บิตที่สำคัญ มีประมาณ 16 หลักทศนิยม

3.2 การใช้งานตัวแปรที่เป็นจำนวนจริง (Floating Point)

ตัวแปรที่เป็นจำนวนจริงสามารถประกาศได้โดยการกำหนดค่าลงตรงหรือใช้คีย์เวิร์ด var:

package main
import "fmt"

func main() {
    var f1 float32 = 3.14 // กำหนดชนิด float32 โดยตรง
    f2 := 3.14            // ถูกตรวจสอบอัตโนมัติเป็นชนิด float64
    fmt.Println(f1, f2)
}

3.3 การคำนวณแบบจำนวนจริงและปัญหาที่เกิดขึ้น

การคำนวณแบบจำนวนจริงอาจ导致การสูญเสียความแม่นยำ การดำเนินการที่มีความแม่นยำมากมักเป็นปัญหาที่พบบ่อยโดยเฉพาะเมื่อลบจำนวนสองจำนวนที่ใกล้เคียงกันมาก

package main
import "fmt"

func main() {
    f1 := .1
    f2 := .2
    f3 := f1 + f2
    fmt.Println(f3) // ผลลัพธ์อาจไม่ได้ .3 ตามที่คาดหวังเนื่องจากปัญหาความแม่นยำ

    // แก้ปัญหาความแม่นยำโดยใช้การแสดงผลที่มีรูปแบบ
    fmt.Printf("%.1f\n", f3) // ผลลัพธ์ถูกแก้ไขเป็น .3
}

4 ประเภทข้อมูลบูลีน (Boolean)

4.1 ภาพรวมของประเภทข้อมูลบูลีน

บูลีนเป็นประเภทข้อมูลที่ง่ายที่สุด และสามารถมีค่าได้เพียงสองค่า: true (จริง) และ false (เท็จ) มันมีบทบาทที่สำคัญมากในคำสั่งเงื่อนไขและโครงสร้างการควบคุมการทำซ้ำ

4.2 การใช้งานตัวแปรบูลีน

การประกาศและใช้งานตัวแปรบูลีน:

package main
import "fmt"

func main() {
    var success bool = true
    var fail bool = false
    fmt.Println("ดำเนินการเสร็จสมบูรณ์:", success)
    fmt.Println("ดำเนินการล้มเหลว:", fail)
}

ค่าบูลีนมักถูกใช้ในคำสั่งเงื่อนไข:

package main
import "fmt"

func main() {
    a := 10
    b := 20
    fmt.Println("a == b:", a == b) // เท็จ
    fmt.Println("a < b:", a < b)   // จริง
}

5 ประเภทข้อมูลสตริง (String)

5.1 ภาพรวมของสตริง

สตริงคือคอลเลกชันของตัวอักษร ในภาษา Go, สตริงเป็นที่ไม่สามารถเปลี่ยนแปลงได้ แต่ละสตริงประกอบด้วยสองส่วน: ตัวชี้ไปที่อาร์เรย์ไบต์ระยะหนึ่ง และความยาว สตริงสามารถบรรจุข้อมูลใด ๆ รวมถึงไบต์

5.2 การใช้งานตัวแปรสตริง

ตัวแปรสตริงสามารถประกาศโดยใช้เครื่องหมายคำพูดดับเบิล " เพื่อสร้าง แต่คุณยังสามารถใช้เครื่องหมาย backticks ` เพื่อสร้างสตริงหลายบรรทัด:

package main
import "fmt"

func main() {
    var s1 string = "hello"
    s2 := "world"
    s3 := `This is a 
    multiple line 
    string`
    fmt.Println(s1)
    fmt.Println(s2)
    fmt.Println(s3)
}

เมื่อสตริงถูกสร้างแล้ว สิ่งที่อยู่ภายในสตริงไม่สามารถเปลี่ยนแปลงได้ การดำเนินการต่อไปนี้ไม่ถูกต้องและจะทำให้เกิดข้อผิดพลาดในการคอมไพล์:

s := "hello"
s[] = 'H` // ข้อผิดพลาดในการคอมไพล์: เนื้อหาของสตริงไม่สามารถเปลี่ยนแปลงได้

5.3 การดำเนินการกับสตริง

สตริงเป็นสิ่งที่พบมากและสำคัญในการเขียนโปรแกรม ภาษา Go มีคำสั่งภายในที่มีคุณสมบัติมากมายสำหรับการจัดการกับสตริง นี่คือแนวทางในการใช้งานบางอย่างที่นิยม

5.3.1 การต่อสตริง

ในภาษา Go, คุณสามารถใช้ตัวดำเนินการบวก (+) เพื่อต่อสตริง ซึ่งเป็นวิธีที่เข้าใจง่ายที่สุด นอกจากนี้เมื่อจัดการกับการต่อสตริงหลายๆ สตริงบ่อยครั้ง แนะนำให้ใช้ strings.Builder เพื่อประสิทธิภาพที่ดีขึ้น

package main

import (
    "fmt"
    "strings"
)

func main() {
    // การต่อสตริงโดยใช้ +
    hello := "Hello, "
    world := "World!"
    result := hello + world
    fmt.Println(result) // ผลลัพธ์: Hello, World!

    // การต่อสตริงโดยใช้ strings.Builder
    var sb strings.Builder
    sb.WriteString("Hello, ")
    sb.WriteString("World!")
    fmt.Println(sb.String()) // ผลลัพธ์: Hello, World!
}

5.3.2 การแบ่งสตริง

การแบ่งสตริงสามารถทำได้โดยใช้ฟังก์ชัน strings.Split ซึ่งจะทำการแบ่งสตริงเป็นส่วนย่อย ๆ โดยใช้ตัวคั่นที่กำหนดไว้

package main

import (
    "fmt"
    "strings"
)

func main() {
    // กำหนดค่าสตริง
    sentence := "Go คือ ภาษาโปรแกรมชิ้นโค้กแห่งเปิด"

    // แบ่งสตริงด้วยช่องว่าง
    words := strings.Split(sentence, " ")
    for _, word := range words {
        fmt.Printf("%s\n", word)
    }
    // ผลลัพธ์:
    // Go
    // คือ
    // ภาษาโปรแกรมชิ้นโค้กแห่งเปิด
}

5.3.3 การเข้าถึงดัชนี

ใน Go, สตริงคือลำดับของไบต์ที่ไม่เปลี่ยนแปลง คุณสามารถใช้การเข้าถึงดัชนีเพื่อเข้าถึงไบต์ที่แน่นอนในสตริง อย่างไรก็ตาม สำคัญที่ต้องระบุว่าเนื่องจากสตริงอาจมีตัวอักษรหลายไบต์ (เช่น ตัวอักษรที่เข้ารหัสด้วย UTF-8) การเข้าถึงดัชนีโดยตรงอาจไม่ให้ผลลัพธ์ตามที่คาดหวัง

package main

import "fmt"

func main() {
    s := "สวัสดี, โลก"
    for i := ; i < len(s); i++ {
        fmt.Printf("%d: %x\n", i, s[i])
    }
    // หมายเหตุ: นี้จะแสดงผลลัพธ์เป็นการแสดงเลขฐานสิบหกของไบต์ ไม่ใช่ตัวอักษร
}

เพื่อหาอักษรตามลำดับในสตริง คุณสามารถใช้ลูป range

package main

import "fmt"

func main() {
    s := "สวัสดี, โลก"
    for index, runeValue := range s {
        fmt.Printf("%d: %U '%c'\n", index, runeValue, runeValue)
    }
    // ผลลัพธ์: ดัชนี, การเข้ารหัส Unicode, และตัวอักษรเองสำหรับแต่ละตัวอักษร
}

5.3.4 การรับความยาว

ฟังก์ชัน len สามารถหาความยาวของสตริงได้ กล่าวคือ ความยาวของลำดับไบต์ที่เป็นพื้นฐาน สำหรับสตริงที่ใช้เข้ารหัสด้วย UTF-8 หากคุณต้องการหาจำนวนตัวอักษร (runes) คุณควรใช้ฟังก์ชัน utf8.RuneCountInString ซึ่งสามารถจัดการตัวอักษรหลายไบต์ได้อย่างถูกต้อง

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    s := "สวัสดี, โลก"
    fmt.Println("ความยาวของไบต์:", len(s)) // แสดงความยาวของไบต์
    fmt.Println("ความยาวของตัวอักษร:", utf8.RuneCountInString(s)) // แสดงความยาวของตัวอักษร
}

จากตัวอย่างข้างต้น เราสามารถเห็นได้ว่า ภาษา Go มีฟังก์ชันต่าง ๆ ที่มีความสามารถในการดำเนินการกับสตริงอย่างหลากหลาย ทำให้ง่ายต่อการทำงานกับสตริงต่าง ๆ เมื่อเขียนโปรแกรมสำคัญที่ต้องใส่ใจถึงความแตกต่างระหว่างไบต์ และ ตัวอักษรโดยเฉพาะอย่างยิ่งเมื่อจัดการกับเซตตัวอักษรที่ไม่ใช่ ASCII