golang流式读取和发送

本文介绍了在gin框架中处理大模型流式读取的需求,以及如何在Post请求中使用`DisableAutoReadResponse`和`Stream`功能实现流式数据发送,同时关注了`Content-Type`设置和`Flush`操作的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#req流式读取 #gin框架流式发送

欢迎来我的博客cjwblog.cn逛逛,虽然没什么内容x

场景
  • 部分大模型(如gpt)的流式读取,可以增加用户体验。
  • gin框架的流式问答,与前端交互。
使用方法
  1. 我在使用框架req 的时候,发现无法从resp.Body流式读取数据,只能完整读出来

原因是框架自动帮我们读取了resp,导致我们无法读取流式的消息。

正常我们获取返回值应该是这样的:

resp := c.c.Post(url).SetQueryParam("key", c.key).SetBody(msg).Do(ctx)
data := resp.String()

想要读取流式可以这么做:

resp := c.c.DisableAutoReadResponse().Post(url).SetQueryParam("key", c.key).SetBody(msg).Do(ctx)
defer resp.Body.Close()

scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
    line := scanner.Text()
    if strings.Contains(line, "text") {
        fmt.Println(line)
    }
}
  1. 现在我们知道了如何从外部读取流式数据,那么我们如何利用web框架发送流式数据呢?

下面以gin框架为例

可以使用func (c *Context) Stream(step func(w io.Writer) bool) bool函数

==具体使用方法如下==(这里我用了自己的代码做了演示):

如果前端有需求,需要加上Header

c.Header("Content-Type", "application/octet-stream")

用bufio缓冲区向前端写数据

stop := c.Stream(func(w io.Writer) bool {
    bw := bufio.NewWriter(w)
    if len(r.Choices) != 0 {
        gptResult.Detail = &r
        gptResult.Id = r.ID
        gptResult.Role = openai.ChatMessageRoleAssistant
        gptResult.Text += r.Choices[0].Delta.Content // 流传输
        marshal, _ := json.Marshal(gptResult)
        if _, err := fmt.Fprintf(bw, "%s\n", marshal); err != nil {
            fmt.Println(err)
            return true
        }
        bw.Flush()
    }
    return false
}) //stop
if stop {
    fmt.Println("stop")
    break
}

顺便讲一下flush吧,按官方文档来说,是为了将写好的数据发送给客户端。

// The Flusher interface is implemented by ResponseWriters that allow
// an HTTP handler to flush buffered data to the client.
type Flusher interface {
    // Flush sends any buffered data to the client.
    Flush()
}

本文由博客一文多发平台 OpenWrite 发布!

### 回答1: 在Golang中使用流式读取超大Excel文件可以使用第三方库"github.com/360EntSecGroup-Skylar/excelize"。该库支持流式读取Excel文件,可以解决内存占用过大的问题。使用时,需要先打开Excel文件,然后使用GetRows方法读取每一行的数据。 ### 回答2: 要使用流式读取超大的Excel文件,可以使用Go语言的Ole库,该库提供了对OLE2文件格式的访问。 首先,需要安装Go语言的Ole库。可以通过以下命令进行安装: ``` go get github.com/go-ole/go-ole ``` 然后,导入Ole库并创建一个OLE reader对象。可以使用如下代码: ```go import ( "github.com/go-ole/go-ole" "github.com/go-ole/go-ole/oleutil" ) func main() { ole.CoInitialize(0) defer ole.CoUninitialize() unknown, _ := oleutil.CreateObject("excel.Application") excel, _ := unknown.QueryInterface(ole.IID_IDispatch) defer excel.Release() workbooks, _ := oleutil.GetProperty(excel, "Workbooks") defer workbooks.Clear() workbook, _ := oleutil.CallMethod(workbooks.ToIDispatch(), "Open", "path/to/file.xlsx") defer workbook.Clear() sheets, _ := oleutil.GetProperty(workbook.ToIDispatch(), "Worksheets") defer sheets.Clear() sheet, _ := oleutil.GetProperty(sheets.ToIDispatch(), "Item", 1) defer sheet.Clear() rows, _ := oleutil.GetProperty(sheet.ToIDispatch(), "Rows") defer rows.Clear() count, _ := rows.GetProperty("Count") rowCount, _ := count.Value().(int) for i := 1; i <= rowCount; i++ { row, _ := oleutil.GetProperty(rows.ToIDispatch(), "Item", i) defer row.Clear() cells, _ := oleutil.GetProperty(row.ToIDispatch(), "Cells") defer cells.Clear() // 获取单元格数据 cell1, _ := oleutil.GetProperty(cells.ToIDispatch(), "Item", 1) defer cell1.Clear() cell2, _ := oleutil.GetProperty(cells.ToIDispatch(), "Item", 2) defer cell2.Clear() // 处理单元格数据 value1 := cell1.Value() value2 := cell2.Value() // TODO: 处理单元格数据 } } ``` 上述代码通过OLE库创建了一个Excel对象,并打开了指定的Excel文件。然后,它获取了第一个工作表,并遍历了每一行的数据。通过调用`GetProperty``CallMethod`方法,可以获取单元格的值。你可以根据自己的需求,处理这些单元格的数据。 需要注意的是,对于大型Excel文件,可能会遇到性能问题。可以通过在循环中添加一些优化策略来提高性能,如批量读取多行数据,避免重复的COM调用等。 希望这个回答能够帮助到你。 ### 回答3: 在Golang中,可以使用excelize库来读取超大的Excel文件。该库提供了流式读取的功能,可以有效地处理超大的Excel文件,而不会导致内存溢出。 首先,需要使用excelize库的OpenReader方法,以只读模式打开Excel文件。然后,可以使用GetSheetNameList方法获取所有的Sheet名称。接下来,可以使用GetRows方法逐行读取指定的Sheet。该方法返回一个二维数组,每一行都是一个字符串切片,表示该行的数据。 为了避免一次性读取所有数据导致的内存溢出,可以使用for循环逐行读取数据,并在每次循环结束后将内存中的数据清空。这样,就可以实现流式读取超大Excel文件的效果。 下面是一个简单的示例代码,用于读取Excel文件的第一个Sheet中的数据: ```go package main import ( "fmt" "github.com/360EntSecGroup-Skylar/excelize" ) func main() { xlsx, err := excelize.OpenFile("example.xlsx") if err != nil { fmt.Println(err) return } // 获取所有的Sheet名称 sheetNameList := xlsx.GetSheetList() // 读取第一个Sheet中的数据 rows, err := xlsx.GetRows(sheetNameList[0]) if err != nil { fmt.Println(err) return } for _, row := range rows { // 处理每一行的数据 // ... // 释放内存 row = nil } // 释放内存 rows = nil } ``` 通过以上方法,就可以实现Golang中对超大Excel文件的流式读取
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值