一、基礎語法
1、Go語言的基本類型有哪些?
Go語言的基礎數據類型有:布爾型、數字型、字符串型、派生類型。布爾型的值只可以是常量 true 或者 false。數字類型包含整型和浮點型。其中整型包括 int8、int16、int32、int64、uint8、uint16、uint32、uint64 和 uintptr,浮點型包括 float32 和 float64。Go 語言中不允許不同類型之間的混合使用,但支持類型的轉換。
var (
isBool bool = true
name string = "go language"
age int = 20
weight float64 = 60.1
)
2、列舉Go語言的控制語句
Go 語言支持普通的控制流程語句:if、switch、for 和循環控制語句:break、continue 和 goto。if 語句將根據條件表達式的結果,決定執行哪條語句塊。switch 語句用於編寫一系列的 if-else 語句。for 語句是 Go 語言中唯一的循環語句,它支持 for-range 格式,可以遍歷字符串、數組、切片、map、管道等。break 跳出當前循環,continue 語句放棄當前循環中的剩餘語句。goto 語句將程序轉到標記的語句處。
for i := 0; i < 10; i++ {
if i == 5 {
continue
}
fmt.Println(i)
if i == 7 {
break
}
}
3、Go語言中的指針有什麼特點?
Go 語言中的指針不能做指針運算,但是可以通過使用 unsafe 包實現指針運算;使用指針時,需要注意內存泄漏和空指針問題;可以使用 new() 和 & 兩種方式來創建指針類型變量,new(T) 返回一個指向類型 T 的零值的指針,& 取某個變量的地址。
// 指針類型的定義和初始化
var p *int
p = &a
// new() 函數用法
p := new(int)
*p = 100
二、並發編程
1、什麼是並發編程?
並發編程是指多個執行路徑同時執行,但不一定是同時完成。在 Go 語言中,可以使用 goroutine 實現並發編程,goroutine 是 Go 語言中的輕量級線程,它可以在很小的棧空間上進行並發運算。
2、如何創建 goroutine?
使用 go 關鍵字即可創建一個 goroutine,即 go f(),其中 f() 是一個函數。
func main() {
go show()
}
func show() {
fmt.Println("Hello, Go")
}
3、如何進行同步操作?
Go 語言提供了 sync 包,通過它可以實現同步操作。sync.WaitGroup 可以用於等待一組 goroutine 的結束。類似於 Java 的 CountDownLatch 或者 C# 的 ManualResetEvent。
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(index int) {
fmt.Println("goroutine", index)
wg.Done()
}(i)
}
wg.Wait()
fmt.Println("all goroutine completed.")
}
三、網絡編程
1、Go語言中如何進行TCP/UDP編程?
Go 語言提供了 net 包可用於 TCP/UDP 編程。使用 net.Listen() 函數監聽端口,使用 net.Dial() 函數與服務器建立連接。基本流程:服務端創建監聽,接受客戶端連接請求,分配 goroutine 處理連接,客戶端通過 Dial() 連接服務端。
2、如何創建一個TCP服務端?
func main() {
ln, err := net.Listen("tcp", "127.0.0.1:8005")
if err != nil {
fmt.Println("listen err:", err)
return
}
defer ln.Close()
fmt.Println("server started, listening on", ln.Addr())
for {
conn, err := ln.Accept()
if err != nil {
fmt.Println("accept err:", err)
continue
}
go handleConn(conn)
}
}
func handleConn(conn net.Conn) {
defer conn.Close()
fmt.Println("accepted client", conn.RemoteAddr())
var buf [512]byte
for {
n, err := conn.Read(buf[:])
if err != nil {
fmt.Println("read err:", err)
return
}
str := string(buf[:n])
fmt.Println("recv:", str)
_, err = conn.Write([]byte("hello, client"))
if err != nil {
fmt.Println("write err:", err)
return
}
}
}
3、如何創建一個UDP客戶端?
func main() {
addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:8007")
if err != nil {
fmt.Println("resolve err:", err)
return
}
conn, err := net.DialUDP("udp", nil, addr)
if err != nil {
fmt.Println("dial err:", err)
return
}
defer conn.Close()
_, err = conn.Write([]byte("hello, server"))
if err != nil {
fmt.Println("write err:", err)
return
}
var buf [512]byte
n, err := conn.Read(buf[:])
if err != nil {
fmt.Println("read err:", err)
return
}
str := string(buf[:n])
fmt.Println("recv:", str)
}
四、Web編程
1、如何創建一個HTTP服務端?
使用 net/http 包中的 http.ListenAndServe() 函數可以創建一個 HTTP 服務端。在定義處理函數時,可以使用 http.HandleFunc() 函數定義多個路由,通過啟動 HTTP 服務,可以通過訪問服務器地址和端口號訪問服務。
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, Go!")
})
fmt.Println("server started at 127.0.0.1:8000")
err := http.ListenAndServe("127.0.0.1:8000", nil)
if err != nil {
fmt.Println("listen err:", err)
}
}
2、如何通過 HTTP 服務端實現文件下載和上傳?
通過實現合適的路由和處理函數,可以方便地實現文件下載和上傳功能。
文件下載示例:
func main() {
http.HandleFunc("/download", func(w http.ResponseWriter, r *http.Request) {
fileName := "./test.txt"
f, err := os.Open(fileName)
if err != nil {
fmt.Println("open file err:", err)
return
}
defer f.Close()
buf := make([]byte, 1024)
for {
n, err := f.Read(buf[:])
if err != nil {
if err == io.EOF {
break
}
fmt.Println("read file err:", err)
return
}
w.Write(buf[:n])
}
})
fmt.Println("server started at 127.0.0.1:8000")
err := http.ListenAndServe("127.0.0.1:8000", nil)
if err != nil {
fmt.Println("listen err:", err)
}
}
文件上傳示例:
func main() {
http.HandleFunc("/upload", func(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
// 接收文件,最大2M
file, header, err := r.FormFile("uploadfile")
if err != nil {
fmt.Println("get upload file err:", err)
return
}
fileName := "./" + header.Filename
defer file.Close()
f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
fmt.Println("create file err:", err)
return
}
defer f.Close()
buf := make([]byte, 1024*2)
for {
n, err := file.Read(buf[:])
if err != nil {
if err == io.EOF {
break
}
fmt.Println("read file err:", err)
return
}
f.Write(buf[:n])
}
fmt.Fprintln(w, "upload success")
} else {
fmt.Fprintln(w, "not support "+r.Method)
}
})
fmt.Println("server started at 127.0.0.1:8000")
err := http.ListenAndServe("127.0.0.1:8000", nil)
if err != nil {
fmt.Println("listen err:", err)
}
}
五、數據庫操作
1、Go語言中如何操作MySQL數據庫?
Go 語言中操作 MySQL 數據庫可以使用第三方庫 go-sql-driver/mysql。通過這個庫可以操作數據庫的增、刪、改、查等操作。使用 database/sql 包可以操作多種不同的數據庫,是一個抽象的數據庫驅動層。
2、如何創建一個MySQL連接?
func main() {
dsn := "root:password@tcp(127.0.0.1:3306)/test"
db, err := sql.Open("mysql", dsn)
if err != nil {
fmt.Println("open mysql error:", err)
return
}
db.SetMaxOpenConns(10)
db.SetMaxIdleConns(5)
defer db.Close()
fmt.Println("mysql connected.")
}
3、如何執行一個MySQL查詢操作?
通過查詢語句和參數傳入查詢語句執行查詢操作即可。使用 Rows.Scan() 函數獲取查詢結果,在查詢執行完畢後關閉 rows。
func main() {
dsn := "root:password@tcp(127.0.0.1:3306)/test"
db, err := sql.Open("mysql", dsn)
if err != nil {
fmt.Println("open mysql error:", err)
return
}
db.SetMaxOpenConns(10)
db.SetMaxIdleConns(5)
defer db.Close()
rows, err := db.Query("SELECT id,name,age FROM user WHERE id=?", 1)
if err != nil {
fmt.Println("query error:", err)
return
}
defer rows.Close()
for rows.Next() {
var id int
var name string
var age int
err := rows.Scan(&id, &name, &age)
if err != nil {
fmt.Println("scan error:", err)
return
}
fmt.Printf("id=%d,name=%s,age=%d\n", id, name, age)
}
}
通過本文的詳細講解,你已經了解了Go語言的一些面試題,並找到了相關的代碼實現。希望這篇文章對你的面試有所幫助!
原創文章,作者:UEDTR,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/361858.html