mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
This pull request standardizes the use of the Go 1.18+ `any` type alias
instead of `interface{}` throughout the codebase. The change improves
code readability and aligns with modern Go best practices. The update
touches many files, including core data structures, code generation
templates, logging utilities, and test data, ensuring consistency across
all usages.
**Type alias migration to `any`:**
* Replaced all instances of `interface{}` with `any` in core data
structures such as `garray` and in generated model structs (e.g.,
`TableUser`, `User1`, `User2`) to modernize type usage.
[[1]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L31-R31)
[[2]](diffhunk://#diff-6c19859cb32c7516ea95ddc8f8235460818eb2f24d2204308e0d9e1b19e7d90fL15-R19)
[[3]](diffhunk://#diff-a15ba2f5e830b4833c47b902515a4f9e5a4f83a3707698f3229b307ec3776b41L15-R18)
[[4]](diffhunk://#diff-52e0837e84d49221d1b810d88fdf78221f36cffcd664fb42f8aba49a79b974dcL15-R19)
[[5]](diffhunk://#diff-11c3457d1a23a4ca6ecd00d6b856289774936b6a708384cf03aff164044e7546L15-R19)
[[6]](diffhunk://#diff-2cff9cf8e6a0cc34087326d8c8149c3bbaf74c76fdbdf5a73daed13cc04249e1L15-R19)
* Updated function signatures, method parameters, and return types from
`interface{}` to `any` in various parts of the codebase, including code
generation, service logic, and logging utilities (e.g., `mlog`).
[[1]](diffhunk://#diff-175edfeea54490b8fe4e18ffcbea5835efaf8f0b8acf623359073987cae7eb76L48-R55)
[[2]](diffhunk://#diff-2b1953fb78cf3593d8c2c7d911e95b65fd0b847c30ed0b4d167d16fe6d781235L54-R74)
[[3]](diffhunk://#diff-e001b7a4b63603b9b14f00de78a4d570bb76c5f57d856a24643f071032e12356L66-R73)
[[4]](diffhunk://#diff-5582954e8a9983988dc8854ad82067fb2ac6269b988e07357ad8db1dfec5f1a0L39-R41)
[[5]](diffhunk://#diff-c5d51d56f487779a2b6207c7ad26c7a20bbadcc846ce094fe60ab4cabff58c51L107-R107)
[[6]](diffhunk://#diff-f96e6a9fdb416eb1804ceaba1fe0ac637bff22c43837f8bb849c2366ce72d4a1L116-R121)
[[7]](diffhunk://#diff-f94c83a1b08ae060d9346f4a6031fc4a7b9a0b894e02d9afaa09018b6598eac0L112-R112)
[[8]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L36-R36)
[[9]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L74-R74)
[[10]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L96-R96)
**Generated code and templates:**
* Adjusted generated files and code generation templates to output `any`
instead of `interface{}` for relevant struct fields and function
signatures, ensuring that new code generation aligns with the updated
convention.
[[1]](diffhunk://#diff-6c19859cb32c7516ea95ddc8f8235460818eb2f24d2204308e0d9e1b19e7d90fL15-R19)
[[2]](diffhunk://#diff-a15ba2f5e830b4833c47b902515a4f9e5a4f83a3707698f3229b307ec3776b41L15-R18)
[[3]](diffhunk://#diff-52e0837e84d49221d1b810d88fdf78221f36cffcd664fb42f8aba49a79b974dcL15-R19)
[[4]](diffhunk://#diff-11c3457d1a23a4ca6ecd00d6b856289774936b6a708384cf03aff164044e7546L15-R19)
[[5]](diffhunk://#diff-2cff9cf8e6a0cc34087326d8c8149c3bbaf74c76fdbdf5a73daed13cc04249e1L15-R19)
[[6]](diffhunk://#diff-175edfeea54490b8fe4e18ffcbea5835efaf8f0b8acf623359073987cae7eb76L48-R55)
[[7]](diffhunk://#diff-e001b7a4b63603b9b14f00de78a4d570bb76c5f57d856a24643f071032e12356L66-R73)
[[8]](diffhunk://#diff-5582954e8a9983988dc8854ad82067fb2ac6269b988e07357ad8db1dfec5f1a0L39-R41)
**Container and utility updates:**
* Refactored the `garray` container implementation and related
constructors/methods to use `[]any` instead of `[]interface{}`, along
with corresponding function signatures.
[[1]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L31-R31)
[[2]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L52-R52)
[[3]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L62-R62)
[[4]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L73-R86)
[[5]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L96-R97)
[[6]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L107-R114)
[[7]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L124-R124)
[[8]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L135-R143)
[[9]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L167-R167)
These changes collectively modernize the codebase and prepare it for
future Go developments by using the idiomatic `any` type.
145 lines
3.9 KiB
Go
145 lines
3.9 KiB
Go
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
// Package gqueue provides dynamic/static concurrent-safe queue.
|
|
//
|
|
// Features:
|
|
//
|
|
// 1. FIFO queue(data -> list -> chan);
|
|
//
|
|
// 2. Fast creation and initialization;
|
|
//
|
|
// 3. Support dynamic queue size(unlimited queue size);
|
|
//
|
|
// 4. Blocking when reading data from queue;
|
|
package gqueue
|
|
|
|
import (
|
|
"math"
|
|
|
|
"github.com/gogf/gf/v2/container/glist"
|
|
"github.com/gogf/gf/v2/container/gtype"
|
|
)
|
|
|
|
// Queue is a concurrent-safe queue built on doubly linked list and channel.
|
|
type Queue struct {
|
|
limit int // Limit for queue size.
|
|
list *glist.List // Underlying list structure for data maintaining.
|
|
closed *gtype.Bool // Whether queue is closed.
|
|
events chan struct{} // Events for data writing.
|
|
C chan any // Underlying channel for data reading.
|
|
}
|
|
|
|
const (
|
|
defaultQueueSize = 10000 // Size for queue buffer.
|
|
defaultBatchSize = 10 // Max batch size per-fetching from list.
|
|
)
|
|
|
|
// New returns an empty queue object.
|
|
// Optional parameter `limit` is used to limit the size of the queue, which is unlimited in default.
|
|
// When `limit` is given, the queue will be static and high performance which is comparable with stdlib channel.
|
|
func New(limit ...int) *Queue {
|
|
q := &Queue{
|
|
closed: gtype.NewBool(),
|
|
}
|
|
if len(limit) > 0 && limit[0] > 0 {
|
|
q.limit = limit[0]
|
|
q.C = make(chan any, limit[0])
|
|
} else {
|
|
q.list = glist.New(true)
|
|
q.events = make(chan struct{}, math.MaxInt32)
|
|
q.C = make(chan any, defaultQueueSize)
|
|
go q.asyncLoopFromListToChannel()
|
|
}
|
|
return q
|
|
}
|
|
|
|
// Push pushes the data `v` into the queue.
|
|
// Note that it would panic if Push is called after the queue is closed.
|
|
func (q *Queue) Push(v any) {
|
|
if q.limit > 0 {
|
|
q.C <- v
|
|
} else {
|
|
q.list.PushBack(v)
|
|
if len(q.events) < defaultQueueSize {
|
|
q.events <- struct{}{}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Pop pops an item from the queue in FIFO way.
|
|
// Note that it would return nil immediately if Pop is called after the queue is closed.
|
|
func (q *Queue) Pop() any {
|
|
return <-q.C
|
|
}
|
|
|
|
// Close closes the queue.
|
|
// Notice: It would notify all goroutines return immediately,
|
|
// which are being blocked reading using Pop method.
|
|
func (q *Queue) Close() {
|
|
if !q.closed.Cas(false, true) {
|
|
return
|
|
}
|
|
if q.events != nil {
|
|
close(q.events)
|
|
}
|
|
if q.limit > 0 {
|
|
close(q.C)
|
|
} else {
|
|
for i := 0; i < defaultBatchSize; i++ {
|
|
q.Pop()
|
|
}
|
|
}
|
|
}
|
|
|
|
// Len returns the length of the queue.
|
|
// Note that the result might not be accurate if using unlimited queue size as there's an
|
|
// asynchronous channel reading the list constantly.
|
|
func (q *Queue) Len() (length int64) {
|
|
bufferedSize := int64(len(q.C))
|
|
if q.limit > 0 {
|
|
return bufferedSize
|
|
}
|
|
return int64(q.list.Size()) + bufferedSize
|
|
}
|
|
|
|
// Size is alias of Len.
|
|
// Deprecated: use Len instead.
|
|
func (q *Queue) Size() int64 {
|
|
return q.Len()
|
|
}
|
|
|
|
// asyncLoopFromListToChannel starts an asynchronous goroutine,
|
|
// which handles the data synchronization from list `q.list` to channel `q.C`.
|
|
func (q *Queue) asyncLoopFromListToChannel() {
|
|
defer func() {
|
|
if q.closed.Val() {
|
|
_ = recover()
|
|
}
|
|
}()
|
|
for !q.closed.Val() {
|
|
<-q.events
|
|
for !q.closed.Val() {
|
|
if bufferLength := q.list.Len(); bufferLength > 0 {
|
|
// When q.C is closed, it will panic here, especially q.C is being blocked for writing.
|
|
// If any error occurs here, it will be caught by recover and be ignored.
|
|
for i := 0; i < bufferLength; i++ {
|
|
q.C <- q.list.PopFront()
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
// Clear q.events to remain just one event to do the next synchronization check.
|
|
for i := 0; i < len(q.events)-1; i++ {
|
|
<-q.events
|
|
}
|
|
}
|
|
// It should be here to close `q.C` if `q` is unlimited size.
|
|
// It's the sender's responsibility to close channel when it should be closed.
|
|
close(q.C)
|
|
}
|