MST

星途 面试题库

面试题:Go语言实现线程安全Map的测试框架搭建

假设你要设计一个针对自定义线程安全Map的测试框架,该Map使用读写锁(sync.RWMutex)来保证线程安全。请阐述你设计的测试框架结构,包括需要测试的方法(如读、写、并发读写等),以及如何使用Go语言的testing包来编写这些测试用例。
35.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

测试框架结构

  1. 初始化部分:在测试开始前,初始化自定义的线程安全Map以及读写锁。
  2. 测试方法
    • 读操作测试:测试从Map中读取数据的功能,确保能正确获取已写入的数据。
    • 写操作测试:测试向Map中写入数据的功能,检查数据是否被正确写入。
    • 并发读写测试:模拟多个读操作和写操作并发执行,验证线程安全性,确保数据一致性且无竞态条件。

使用Go语言testing包编写测试用例

  1. 导入必要的包
package main

import (
    "sync"
    "testing"
)
  1. 定义自定义线程安全Map
type ThreadSafeMap struct {
    data  map[string]interface{}
    mutex sync.RWMutex
}

func NewThreadSafeMap() *ThreadSafeMap {
    return &ThreadSafeMap{
        data: make(map[string]interface{}),
    }
}

func (m *ThreadSafeMap) Get(key string) (interface{}, bool) {
    m.mutex.RLock()
    defer m.mutex.RUnlock()
    value, exists := m.data[key]
    return value, exists
}

func (m *ThreadSafeMap) Set(key string, value interface{}) {
    m.mutex.Lock()
    defer m.mutex.Unlock()
    m.data[key] = value
}
  1. 读操作测试用例
func TestRead(t *testing.T) {
    m := NewThreadSafeMap()
    m.Set("key1", "value1")
    value, exists := m.Get("key1")
    if!exists || value != "value1" {
        t.Errorf("Expected value 'value1', but got '%v'", value)
    }
}
  1. 写操作测试用例
func TestWrite(t *testing.T) {
    m := NewThreadSafeMap()
    m.Set("key1", "value1")
    value, exists := m.Get("key1")
    if!exists || value != "value1" {
        t.Errorf("Expected value 'value1' to be set, but got '%v'", value)
    }
}
  1. 并发读写测试用例
func TestConcurrentReadWrite(t *testing.T) {
    m := NewThreadSafeMap()
    var wg sync.WaitGroup

    numWriters := 10
    numReaders := 20

    for i := 0; i < numWriters; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            key := "key" + string(id)
            m.Set(key, "value"+string(id))
        }(i)
    }

    for i := 0; i < numReaders; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            key := "key" + string(id%numWriters)
            _, exists := m.Get(key)
            if!exists {
                t.Errorf("Expected key '%s' to exist", key)
            }
        }(i)
    }

    wg.Wait()
}