Apabila melakukan pertanyaan pangkalan data, kami sering menghadapi pertanyaan paging. Walau bagaimanapun, apabila pertanyaan bernombor dibatalkan, ketidaktepatan masa kadangkala boleh berlaku. Isu ini penting untuk aplikasi yang memerlukan masa yang tepat. Dalam artikel ini, editor PHP Baicao akan memperkenalkan kepada anda cara menangani masalah ini untuk memastikan ketepatan dan ketepatan masa. Kami akan meneroka beberapa kemungkinan punca dan penyelesaian untuk membantu anda memahami dan menangani masalah ini dengan lebih baik.
Saya mempunyai objek yang digunakan untuk membuat pertanyaan sql bernombor yang membolehkan untuk menjalankan pertanyaan secara tidak segerak:
type pagedquery[t any] struct { results chan []*t errors chan error done chan error quit chan error client *sql.db } func newpagedquery[t any](client *sql.db) *pagedquery[t] { return &pagedquery[t]{ results: make(chan []*t, 1), errors: make(chan error, 1), done: make(chan error, 1), quit: make(chan error, 1), client: client, } } func (paged *pagedquery[t]) requestasync(ctx context.context, queries ...*query) { conn, err := client.conn(ctx) if err != nil { paged.errors <- err return } defer func() { conn.close() paged.done <- nil }() for i, query := range queries { select { case <-ctx.done(): return case <-paged.quit: return default: } rows, err := conn.querycontext(ctx, query.string, query.arguments...) if err != nil { paged.errors <- err return } data, err := sql.readrows[t](rows) if err != nil { paged.errors <- err return } paged.results <- data } }
Saya cuba menguji kod ini, khususnya bahagian pembatalan. Kod ujian saya kelihatan seperti ini:
svc, mock := createServiceMock("TEST_DATABASE", "TEST_SCHEMA") mock.ExpectQuery(regexp.QuoteMeta("TEST QUERY")). WithArgs(...). WillReturnRows(mock.NewRows([]string{"t", "v", "o", "c", "h", "l", "vw", "n"})) ctx, cancel := context.WithCancel(context.Background()) go svc.requestAsync(ctx, query1, query2, query3, query4) time.Sleep(50 * time.Millisecond) cancel() results := make([]data, 0) loop: for { select { case <-query.Done: break loop case err := <-query.Errors: Expect(err).ShouldNot(HaveOccurred()) case r := <-query.Results: results = append(results, r...) } } Expect(results).Should(BeEmpty()) Expect(mock.ExpectationsWereMet()).ShouldNot(HaveOccurred()) // fails here
Masalah yang saya hadapi ialah ujian ini kadangkala gagal pada baris yang ditunjukkan oleh ulasan saya, kerana apabila cancel()
dipanggil, tiada jaminan bahawa apabila saya menyemak < pada kenyataan kod>tukar
- ctx.done atau <-exit
. Pelaksanaan boleh berlaku di mana-mana sahaja dalam gelung sehingga saya menghantar keputusan ke saluran results
. Tetapi itu tidak masuk akal kerana pelaksanaan harus disekat sehingga saya menerima data daripada saluran results
, yang saya tidak akan lakukan sehingga saya memanggil cancel()
. Selain itu, saya bergantung pada pakej sqlmock untuk ujian sql, yang tidak membenarkan apa-apa jenis pertanyaan sql kabur. Mengapa saya mendapat gangguan ini dan bagaimana saya membetulkannya? cancel()
时,不能保证在我检查 < 的 <code>switch
语句处执行 - ctx.done 或 <-退出
。执行可以在循环中的任何位置进行,直到我将结果发送到 results
通道。但这没有意义,因为执行应该阻塞,直到我从 results
通道接收到数据,直到我调用 cancel()
后我才会这样做。此外,我依靠 sqlmock 包进行 sql 测试,它不允许对 sql 查询进行任何类型的模糊检查。为什么我会遇到此故障以及如何修复它?
我的问题是由于我自己对 go 通道缺乏了解而导致的。我认为,通过创建 chan([]*t, 1)
意味着通道在满时(即当它包含单个项目时)会阻塞,但事实并非如此。相反,当我尝试在缓冲区已满时发送到通道时,会发生阻塞。因此,通过像这样修改 results
chan([]*t, 1)
ia bermakna saluran akan disekat apabila penuh (iaitu apabila ia mengandungi satu item), tetapi ini tidak berlaku. Sebaliknya, apabila saya cuba menghantar ke saluran apabila penimbal penuh, penyekatan berlaku. Jadi dengan mengubah suai hasil
seperti ini: 🎜
func NewPagedQuery[T any](client *sql.DB) *PagedQuery[T] { return &PagedQuery[T]{ Results: make(chan []*T), // Remove buffer here Errors: make(chan error, 1), Done: make(chan error, 1), Quit: make(chan error, 1), client: client, } }
Atas ialah kandungan terperinci Menguji untuk mengendalikan pemasaan yang tidak tepat apabila membatalkan pertanyaan bernombor. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!