【架构优化】list设置容量,避免动态扩容

This commit is contained in:
hahwu 2026-02-05 15:11:31 +08:00
parent e5730c206e
commit 46a76843a9
20 changed files with 133 additions and 99 deletions

View File

@ -20,7 +20,7 @@ func GetInitList() []int {
log.Debug("GetInitList err: %v", err)
return nil
}
r := make([]int, 0)
r := make([]int, 0, len(data))
for k, v := range data {
IsInit := gamedata.GetIntValue(v, "Init")
if IsInit == 1 {
@ -47,7 +47,7 @@ func GetAllId() []int {
log.Debug("GetAllId err: %v", err)
return nil
}
r := make([]int, 0)
r := make([]int, 0, len(data))
for k := range data {
Id, _ := strconv.Atoi(k)
r = append(r, Id)

View File

@ -185,7 +185,7 @@ func GetSpecialShopGrade(Money float64, Type int) int {
if err != nil {
return 0
}
l := make([]grade, 0)
l := make([]grade, 0, len(data))
for _, v := range data {
if gamedata.GetIntValue(v, "Type") != Type {
continue

View File

@ -21,7 +21,7 @@ func GetJackpotId() []int {
if err != nil {
return nil
}
ret := make([]int, 0)
ret := make([]int, 0, len(data))
for k := range data {
ret = append(ret, GoUtil.Int(k))
}

View File

@ -18,7 +18,7 @@ func GetInitList() []int {
if err != nil {
return nil
}
ret := make([]int, 0)
ret := make([]int, 0, len(data))
for k, v := range data {
Init := gamedata.GetIntValue(v, "Init")
if Init == 1 {
@ -33,7 +33,7 @@ func GetAllList() []int {
if err != nil {
return nil
}
ret := make([]int, 0)
ret := make([]int, 0, len(data))
for k := range data {
ret = append(ret, GoUtil.Int(k))
}

View File

@ -20,7 +20,7 @@ func GetInitList() []int {
log.Debug("GetInitList err: %v", err)
return nil
}
r := make([]int, 0)
r := make([]int, 0, len(data))
for k, v := range data {
IsInit := gamedata.GetIntValue(v, "Init")
if IsInit == 1 {
@ -47,7 +47,7 @@ func GetAllId() []int {
log.Debug("GetAllId err: %v", err)
return nil
}
r := make([]int, 0)
r := make([]int, 0, len(data))
for k := range data {
Id, _ := strconv.Atoi(k)
r = append(r, Id)

View File

@ -162,7 +162,7 @@ func GetFastProduceReward(Energy int) []*item.Item {
Id string
Energy float64
}
sortedList := make([]sortData, 0)
sortedList := make([]sortData, 0, len(data))
energy := float64(Energy) / 10.0
for k, v := range data {
dataEnergy := gamedata.GetFloatValue(v, "EnergyValue")
@ -404,7 +404,7 @@ func GetLuckyCatMaxEarning(Remain int) int {
t int
e int
}
l := make([]d, 0)
l := make([]d, 0, len(data))
for k, v := range data {
t := GoUtil.Int(k)
e := gamedata.GetIntValue(v, "Earn")

View File

@ -266,7 +266,7 @@ func GetAllId() []int {
if err != nil {
return []int{}
}
key := make([]int, 0)
key := make([]int, 0, len(data))
for k := range data {
key = append(key, GoUtil.Int(k))
}

View File

@ -65,7 +65,7 @@ func GetPassGem(Id int) []int {
}
Gem := gamedata.GetStringValue(data, "Gem")
strArr := strings.Split(Gem, "|")
result := make([]int, 0)
result := make([]int, 0, len(strArr))
for _, v := range strArr {
a, _ := strconv.Atoi(v)
result = append(result, a)

View File

@ -103,11 +103,11 @@ func GetStartOrderInfo(Id int) (int, int) {
}
func GetStartOrderList() []*gamedata.StartOrderData {
ret := make([]*gamedata.StartOrderData, 0)
data, err := gamedata.GetData(CFG_START_ORDER)
if err != nil {
return ret
return []*gamedata.StartOrderData{}
}
ret := make([]*gamedata.StartOrderData, 0, len(data))
for k, v := range data {
OrderId, _ := strconv.Atoi(k)
ret = append(ret, &gamedata.StartOrderData{
@ -127,11 +127,11 @@ func GetStartOrderList() []*gamedata.StartOrderData {
}
func GetStartOrderByStep(id int) []*gamedata.StartOrderData {
ret := make([]*gamedata.StartOrderData, 0)
data, err := gamedata.GetData(CFG_START_ORDER)
if err != nil {
return ret
return []*gamedata.StartOrderData{}
}
ret := make([]*gamedata.StartOrderData, len(data))
for k, v := range data {
stepVal := gamedata.GetIntValue(v, "step")
if int(stepVal) == id {

View File

@ -53,7 +53,7 @@ func GetNewLevel(Template int, Score int, Reward []int) []int {
if err != nil {
return nil
}
NewReward := make([]int, 0)
NewReward := make([]int, 0, len(data))
for _, v := range data {
if gamedata.GetIntValue(v, "Template") != Template {
continue
@ -72,7 +72,7 @@ func GetFreeChargeItems(Template int, Reward []int) []*item.Item {
if err != nil {
return nil
}
Items := make([]*item.Item, 0)
Items := make([]*item.Item, 0, len(data))
for _, v := range data {
if gamedata.GetIntValue(v, "Template") != Template {
continue
@ -90,7 +90,7 @@ func GetLowChargeItems(Template int, Reward []int) []*item.Item {
if err != nil {
return nil
}
Items := make([]*item.Item, 0)
Items := make([]*item.Item, 0, len(data))
for _, v := range data {
if gamedata.GetIntValue(v, "Template") != Template {
continue
@ -108,7 +108,7 @@ func GetHighChargeItems(Template int, Reward []int) []*item.Item {
if err != nil {
return nil
}
Items := make([]*item.Item, 0)
Items := make([]*item.Item, 0, len(data))
for _, v := range data {
if gamedata.GetIntValue(v, "Template") != Template {
continue

View File

@ -126,11 +126,11 @@ func GetTriggerCd() int {
}
func GetFoodItem() []int {
r := make([]int, 0)
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "Food")
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for _, v := range strings.Split(gamedata.GetStringValue(data, "Value"), ",") {
if v == "" {
continue
@ -142,11 +142,11 @@ func GetFoodItem() []int {
}
func GetCleanItem() []int {
r := make([]int, 0)
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "Clean")
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for _, v := range strings.Split(gamedata.GetStringValue(data, "Value"), ",") {
if v == "" {
continue
@ -157,11 +157,11 @@ func GetCleanItem() []int {
return r
}
func GetToyItem() []int {
r := make([]int, 0)
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "Toy")
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for _, v := range strings.Split(gamedata.GetStringValue(data, "Value"), ",") {
if v == "" {
continue
@ -172,11 +172,11 @@ func GetToyItem() []int {
return r
}
func GetDailyItem() []int {
r := make([]int, 0)
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "Daily")
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for _, v := range strings.Split(gamedata.GetStringValue(data, "Value"), ",") {
if v == "" {
continue
@ -188,11 +188,11 @@ func GetDailyItem() []int {
}
func GetPremiumItem() []int {
r := make([]int, 0)
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "PremiumItem")
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for _, v := range strings.Split(gamedata.GetStringValue(data, "Value"), ",") {
if v == "" {
continue
@ -278,11 +278,11 @@ func GetInteractPExp(Id int) int {
}
func GetInitDecorate() []int {
r := make([]int, 0)
data, err := gamedata.GetData(CFG_PLAYROOM_DECORATE)
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for k, v := range data {
if gamedata.GetIntValue(v, "Init") == 1 {
r = append(r, GoUtil.Int(k))
@ -292,11 +292,11 @@ func GetInitDecorate() []int {
}
func GetDecorateList() []int {
r := make([]int, 0)
data, err := gamedata.GetData(CFG_PLAYROOM_DECORATE)
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for k := range data {
r = append(r, GoUtil.Int(k))
}
@ -339,11 +339,11 @@ func GetPhysiologyDuration(Id int, Num int) int {
}
func GetPhysiologyTypeList() []int {
r := make([]int, 0)
data, err := gamedata.GetData(CFG_PLAYROOM_PHYSIOLOGY_TYPE)
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for k := range data {
r = append(r, GoUtil.Int(k))
}
@ -401,11 +401,11 @@ func IsPlayCat(Id int) bool {
}
func GetInitAirList() []int {
r := make([]int, 0)
data, err := gamedata.GetData(CFG_PLAYROOM_AIR)
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for k, v := range data {
if gamedata.GetIntValue(v, "Init") == 1 {
r = append(r, GoUtil.Int(k))
@ -415,11 +415,11 @@ func GetInitAirList() []int {
}
func GetAirList() []int {
r := make([]int, 0)
data, err := gamedata.GetData(CFG_PLAYROOM_AIR)
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for k := range data {
r = append(r, GoUtil.Int(k))
}
@ -427,11 +427,11 @@ func GetAirList() []int {
}
func GetInitDressList() []int {
r := make([]int, 0)
data, err := gamedata.GetData(CFG_PLAYROOM_DRESS)
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for k, v := range data {
if gamedata.GetIntValue(v, "Init") == 1 {
r = append(r, GoUtil.Int(k))
@ -441,11 +441,11 @@ func GetInitDressList() []int {
}
func GetDressList() []int {
r := make([]int, 0)
data, err := gamedata.GetData(CFG_PLAYROOM_DRESS)
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for k := range data {
r = append(r, GoUtil.Int(k))
}
@ -490,7 +490,7 @@ func GetDailyTask(Type int) map[int]string {
return nil
}
r := make(map[int]string)
r1 := make([]int, 0)
r1 := make([]int, 0, len(data))
r2 := make(map[int]string)
for k, v := range data {
if gamedata.GetIntValue(v, "Type") == Type {
@ -548,11 +548,11 @@ func GetTaskJackpotReward(Id int) []*item.Item {
}
func GetPhysiologyList(MoodType int) []int {
r := make([]int, 0)
data, err := gamedata.GetData(CFG_PLAYROOM_PHYSIOLOGY_TYPE)
if err != nil {
return []int{}
}
r := make([]int, 0, len(data))
for k, v := range data {
if gamedata.GetIntValue(v, "MType") == MoodType {
r = append(r, GoUtil.Int(k))
@ -565,47 +565,6 @@ func GetInteractIdBath() []int {
return []int{11, 12, 13}
}
func GetOrderItem(Star int) map[int][]gamedata.PetOrderItem {
data, err := gamedata.GetData(CFG_PLAYROOM_ORDERITEM)
if err != nil {
log.Debug("GetOrderItem err:%v", err)
return nil
}
r := make(map[int][]gamedata.PetOrderItem)
for k, v := range data {
ItemStar := gamedata.GetIntValue(v, "Star")
if ItemStar > 0 && ItemStar > Star {
continue
}
Id := GoUtil.Int(k)
Type := gamedata.GetIntValue(v, "Type")
if Type == 0 {
continue
}
if _, ok := r[Type]; !ok {
r[Type] = make([]gamedata.PetOrderItem, 0)
}
if Id == 0 {
log.Debug("GetOrderItem Id is 0, Type:%v", Type)
continue
}
GradeStr := gamedata.GetStringValue(v, "Grade")
Grade := make([]int, 0)
for _, v1 := range strings.Split(GradeStr, ",") {
v2 := GoUtil.Int(v1)
if v2 > 0 {
Grade = append(Grade, v2)
}
}
r[Type] = append(r[Type], gamedata.PetOrderItem{
Id: Id,
Star: ItemStar,
Grade: Grade,
})
}
return r
}
func GetOrderItemByGrade(Grade int) map[int][]int {
data, err := gamedata.GetData(CFG_PLAYROOM_ORDERITEM)
if err != nil {

View File

@ -39,7 +39,7 @@ func (p *Player) GetVisitorPlayer() int {
if FriendMod.CheckFriend(k) {
PlayerList = append(PlayerList, sortData{k, v.Time})
} else {
PlayerList2 = append(PlayerList, sortData{k, v.Time})
PlayerList2 = append(PlayerList2, sortData{k, v.Time})
}
}
if len(PlayerList) != 0 {

View File

@ -605,6 +605,22 @@ func ReqGmCommand_(player *Player, Command string) error {
LimitedTimeEventMod := player.PlayMod.getLimitedTimeEventMod()
LimitedTimeEventMod.AddEvent(Id, Cd)
player.PushClientRes(LimitedTimeEventMod.BackData())
case "debugMsg":
to, _ := strconv.Atoi(arg[1])
num, _ := strconv.Atoi(arg[1])
for i := 0; i < num; i++ {
uid := 100100000 + i
if uid == int(player.M_DwUin) {
continue
}
SendMsgToCenterAsync(&MsgMod.Msg{
From: uid,
To: to,
Type: MsgMod.HANDLE_TYPE_APPLY,
SendT: GoUtil.Now(),
HandleType: MsgMod.HANDLE_MOD_PLAYER_MSG,
})
}
default:
return fmt.Errorf("Player %d ReqGmCommand:%v not found", player.M_DwUin, arg)
}

View File

@ -47,8 +47,14 @@ func (p *Player) HandleMsg(m *msg.Msg) {
p.Recover(backup) //还原Player的数据
return
}
p.ProcessTrigger()
p.SendClientRes()
// 处理在线消息
if m.H == msg.MSG_TYPE_ONLINE {
p.ProcessTrigger()
p.SendClientRes()
} else {
p.Msg = make([]PlayerMsg, 0)
}
}
// 消息处理
@ -503,6 +509,8 @@ func (p *Player) handle(m *msg.Msg) error {
}
case msg.HANDLE_TYPE_FRIEND_SPONSOER:
p.AddLog(m.From, friend.LOG_TYPE_FRIEND_SPONSOR_GET, "", m.SendT)
case msg.SERVER_PLAYER_SYNC_LOGOUT_MSG:
p.LoginBackData()
default:
log.Debug("uid : %d, handle msg type : %d not exist", p.M_DwUin, m.Type)
}

View File

@ -314,8 +314,16 @@ func PlayerLoginHandler(data *msg.Msg) (interface{}, error) {
ReplyPlayerMsgASync(data, nil)
// 在锁外发送离线消息
for _, message := range messagesToSend {
message.H = msg.MSG_TYPE_ONLINE // 标记为在线消息
SendMsgToNodeAsync(message, node)
}
SendMsgToNodeAsync(&msg.Msg{
From: data.From,
To: data.From,
Type: msg.SERVER_PLAYER_SYNC_LOGOUT_MSG,
HandleType: msg.HANDLE_MOD_PLAYER_MSG,
Extra: len(messagesToSend),
}, node) // 发送离线消息处理完成通知
log.Debug("[Middleware] Player sync logout message player id: %v, len: %d", data.From, len(messagesToSend))
return nil, nil
}

View File

@ -31,6 +31,10 @@ const (
var MSG_ZERO_UPDATE = &Msg{Type: SERVER_ZERO_UPDATE}
var MSG_NOON_UPDATE = &Msg{Type: SERVER_NOON_UPDATE}
const (
MSG_TYPE_ONLINE = 0 // 在线消息
MSG_TYPE_OFFLINE = 1 // 离线消息
)
const (
HANDLE_MOD_PLAYER_MSG = 20001 // 玩家消息
HANDLE_MOD_CLUSTER_MSG = 20002 // 集群消息
@ -147,7 +151,8 @@ const (
HANDLE_TYPE_CATNIP_SEND_EMOJI // 发送猫薄荷表情
HANDLE_TYPE_CHAMPSHIP_MY_RANK // 锦标赛我的排名
HANDLE_TYPE_LOGIN // 玩家登录处理
HANDLE_TYPE_LOGIN // 玩家登录处理
SERVER_PLAYER_SYNC_LOGOUT_MSG // 玩家处理完离线消息
)
const (

View File

@ -24,10 +24,13 @@ func (p *Player) PlayroomBackData() {
FriendMod := p.PlayMod.getFriendMod()
r.Status = int32(PlayroomMod.Status)
r.Items = item.ItemToMsg(PlayroomMod.Reward)
Opponent := make([]*proto.RoomOpponent, 0)
FriendList := make([]*proto.FriendRoom, 0)
// 预分配切片容量,避免动态扩容
visitorCount := len(PlayroomMod.Visitor)
Opponent := make([]*proto.RoomOpponent, 0, visitorCount)
FriendList := make([]*proto.FriendRoom, 0, len(FriendMod.GetFriendList()))
if PlayroomMod.Target == 0 {
PlayroomMod.Target = p.GetVisitorPlayer()
PlayroomMod.SetTarget(p.GetVisitorPlayer())
}
TargerRoom := &proto.FriendRoom{}
if PlayroomMod.Target != 0 {
@ -74,8 +77,11 @@ func (p *Player) PlayroomBackData() {
r.Opponent = Opponent
r.Friend = FriendList
r.Target = TargerRoom
Collect := make([]*proto.PlayroomCollectInfo, 0)
for _, v := range PlayroomMod.GetCollect() {
// 预分配装饰品切片容量
collectList := PlayroomMod.GetCollect()
Collect := make([]*proto.PlayroomCollectInfo, 0, len(collectList))
for _, v := range collectList {
Collect = append(Collect, &proto.PlayroomCollectInfo{
Id: int32(v.Id),
AddTime: v.AddTime,
@ -98,14 +104,16 @@ func (p *Player) PlayroomBackData() {
})
Dress[int32(v.Part)] = PlayroomDress
}
ChipMessage := make([]*proto.ChipInfo, 0)
// 预分配芯片列表容量
ChipMessage := make([]*proto.ChipInfo, 0, len(PlayroomMod.ChipList))
for _, v := range PlayroomMod.ChipList {
ChipMessage = append(ChipMessage, &proto.ChipInfo{
Uid: int64(v.Uid),
EmojiId: int32(v.Emoji),
})
}
AdWatch := make([]*proto.AdItem, 0)
// 预分配广告列表容量
AdWatch := make([]*proto.AdItem, 0, len(PlayroomMod.ADItem))
for k, v := range PlayroomMod.ADItem {
AdWatch = append(AdWatch, &proto.AdItem{
Watch: int32(v.Watch),
@ -116,8 +124,10 @@ func (p *Player) PlayroomBackData() {
r.Dress = Dress
r.DressSet = GoUtil.MapIntToInt32(PlayroomMod.GetDressSet())
PetAir := make([]*proto.PlayroomAirInfo, 0)
for _, v := range PlayroomMod.GetPetAir() {
// 预分配宠物空气列表容量
petAirList := PlayroomMod.GetPetAir()
PetAir := make([]*proto.PlayroomAirInfo, 0, len(petAirList))
for _, v := range petAirList {
PetAir = append(PetAir, &proto.PlayroomAirInfo{
Id: int32(v.Id),
AddTime: int64(v.AddTime),
@ -307,8 +317,10 @@ func (p *Player) GetChampshipRank() (int, int) {
// 返回好友信息
func (p *Player) FriendListBackData() {
FriendMod := p.PlayMod.getFriendMod()
var fl []*proto.ResPlayerSimple
for k, v := range FriendMod.GetFriendList() {
friendList := FriendMod.GetFriendList()
// 预分配切片容量
fl := make([]*proto.ResPlayerSimple, 0, len(friendList))
for k, v := range friendList {
if k == int(p.M_DwUin) {
continue
}
@ -319,7 +331,8 @@ func (p *Player) FriendListBackData() {
fl = append(fl, ps)
}
}
ReqFriendList := make([]int64, 0)
// 预分配申请列表容量
ReqFriendList := make([]int64, 0, len(FriendMod.SendApply))
for k := range FriendMod.SendApply {
ReqFriendList = append(ReqFriendList, int64(k))
}
@ -333,7 +346,8 @@ func (p *Player) FriendListBackData() {
func (p *Player) FriendApplyBackData() {
FriendMod := p.PlayMod.getFriendMod()
var al []*proto.ResFriendApplyInfo
// 预分配切片容量
al := make([]*proto.ResFriendApplyInfo, 0, len(FriendMod.ApplyList))
for k, v := range FriendMod.ApplyList {
ps := G_GameLogicPtr.GetResSimplePlayerByUid(k)
if ps != nil {
@ -350,7 +364,8 @@ func (p *Player) FriendApplyBackData() {
func (p *Player) FriendLogBackData() {
FriendMod := p.PlayMod.getFriendMod()
var log []*proto.ResFriendLog
// 预分配切片容量
log := make([]*proto.ResFriendLog, 0, len(FriendMod.Log))
for _, v := range FriendMod.Log {
ps := G_GameLogicPtr.GetResSimplePlayerByUid(v.Uid)
if ps == nil {
@ -367,7 +382,8 @@ func (p *Player) FriendLogBackData() {
Upvote: v.Upvote,
})
}
var reply []*proto.ResFriendReply
// 预分配回复列表容量
reply := make([]*proto.ResFriendReply, 0, len(FriendMod.ReplyList))
for _, v := range FriendMod.ReplyList {
ps := G_GameLogicPtr.GetResSimplePlayerByUid(v.Uid)
if ps == nil {
@ -393,7 +409,8 @@ func (p *Player) FriendLogBackData() {
func (p *Player) FriendCardBackData() {
FriendMod := p.PlayMod.getFriendMod()
var msgList []*proto.ResFriendCard
// 预分配切片容量
msgList := make([]*proto.ResFriendCard, 0, len(FriendMod.Card))
for _, v := range FriendMod.Card {
m := GetCardInfoMsg(v)
msgList = append(msgList, m)

View File

@ -246,10 +246,12 @@ func (p *PlayerMod) ClearData(player *Player) {
}
if p.is_update && !p.IsBlackList() {
//序列化模块
var buf bytes.Buffer
encode := gob.NewEncoder(&buf)
buf := bufferPool.Get().(*bytes.Buffer)
buf.Reset() // 清空之前的数据
encode := gob.NewEncoder(buf)
err := encode.Encode(p.mod_list)
if err != nil {
bufferPool.Put(buf) // 即使出错也要归还
log.Debug("uid: %d, SaveData, playmod error %v", player.M_DwUin, err)
return
}
@ -262,10 +264,12 @@ func (p *PlayerMod) ClearData(player *Player) {
err = db.SavePlayerModData(modData)
if err != nil {
bufferPool.Put(buf) // 即使出错也要归还
log.Debug("uid: %d, SaveData, playmod error %v", player.M_DwUin, err)
return
}
p.is_update = false
bufferPool.Put(buf) // 归还到对象池
}
}

View File

@ -1,6 +1,7 @@
package game
import (
"bytes"
"context"
"database/sql"
"fmt"
@ -13,6 +14,12 @@ import (
"time"
)
var serverBufferPool = sync.Pool{
New: func() interface{} {
return bytes.NewBuffer(make([]byte, 0, 24*1024*1024))
},
}
const (
FRIEND_MGR_KEY = "FRIEND_MGR"
RANK_MGR_KEY = "RANK_MGR"

View File

@ -14,9 +14,16 @@ import (
"reflect"
"strconv"
"strings"
"sync"
"time"
)
var bufferPool = sync.Pool{
New: func() interface{} {
return bytes.NewBuffer(make([]byte, 0, 128*1024))
},
}
// 实例化一个通过字符串映射函数切片的map
var eventByName = make(map[string][]*EventObj)
@ -219,12 +226,15 @@ func String(a interface{}) string {
}
func GobMarshal(data interface{}) ([]byte, error) {
var buf bytes.Buffer
encode := gob.NewEncoder(&buf)
buf := bufferPool.Get().(*bytes.Buffer)
buf.Reset() // 清空之前的数据
encode := gob.NewEncoder(buf)
err := encode.Encode(data)
if err != nil {
bufferPool.Put(buf) // 即使出错也要归还
return nil, err
}
bufferPool.Put(buf) // 归还到对象池
return buf.Bytes(), nil
}