MST

星途 面试题库

面试题:Go语言底层指针操作与内存管理

在Go语言中,你知道unsafe包可以进行一些底层的指针操作。假设你正在开发一个高性能的内存池,需要通过unsafe包对内存进行精准的分配与释放,减少GC压力。请描述实现一个简单内存池的思路,包括如何使用指针操作来管理内存块的分配与回收,并给出关键代码片段。
43.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 内存块划分:将大块内存划分成固定大小的小块,这些小块就是我们内存池中的基本单位。
  2. 指针管理:使用指针来标记每个小块内存的位置以及是否被使用。
  3. 分配逻辑:遍历内存块链表,找到未使用的内存块,标记为已使用并返回其指针。
  4. 回收逻辑:将使用完的内存块标记为未使用,重新加入可用链表。

关键代码片段

package main

import (
    "fmt"
    "unsafe"
)

// 定义内存块大小
const blockSize = 1024

// 定义内存块结构体
type block struct {
    next *block
    used bool
}

// 定义内存池结构体
type MemoryPool struct {
    head *block
}

// 创建新的内存池
func NewMemoryPool() *MemoryPool {
    // 申请大块内存
    rawMem := make([]byte, blockSize*10)
    memPtr := (*block)(unsafe.Pointer(&rawMem[0]))

    // 初始化内存块链表
    for i := 0; i < 9; i++ {
        memPtr.next = (*block)(unsafe.Pointer(uintptr(unsafe.Pointer(memPtr)) + blockSize))
        memPtr.used = false
        memPtr = memPtr.next
    }
    memPtr.next = nil
    memPtr.used = false

    return &MemoryPool{head: (*block)(unsafe.Pointer(&rawMem[0]))}
}

// 从内存池分配内存
func (mp *MemoryPool) Allocate() unsafe.Pointer {
    current := mp.head
    for current != nil {
        if!current.used {
            current.used = true
            return unsafe.Pointer(current)
        }
        current = current.next
    }
    return nil
}

// 回收内存到内存池
func (mp *MemoryPool) Free(ptr unsafe.Pointer) {
    if ptr == nil {
        return
    }
    blockPtr := (*block)(ptr)
    blockPtr.used = false
}

你可以使用以下方式调用:

func main() {
    pool := NewMemoryPool()
    ptr1 := pool.Allocate()
    ptr2 := pool.Allocate()
    fmt.Printf("Allocated ptr1: %v\n", ptr1)
    fmt.Printf("Allocated ptr2: %v\n", ptr2)

    pool.Free(ptr1)
    fmt.Println("Freed ptr1")

    newPtr := pool.Allocate()
    fmt.Printf("New allocated ptr: %v\n", newPtr)
}