GO語言核心30講 實戰與應用 (io包,bufio包,os包,網絡服務,http,性能分析)

?原站地址:Go語言核心36講_Golang_Go語言-極客時間

一、io包中的接口和工具

1.?strings.Builder、strings.Reader 和 bytes.Buffer?這些類型實現了 io 包的很多接口,目的是什么

? ? 是為了提高不同程序實體之間的互操作性。?程序實體是指比如網絡和文件。

? ? 比如?io.Copy:??func Copy(dst Writer, src Reader) (written int64, err error)

? ? 里面的?Writer 和 Reader 可以是網絡,也可以是文件,只要實現了io.Reader接口和io.Writer接口就都可以了。可以把不同的實體抽象成一個統一的實體。

2. 擴展接口和實現類型的區別是什么?

? ?實現類型是一個結構體; 擴展接口只是通過結構體的方式,嵌入了其他數據類型,達到擴展原有數據類型功能的目的,

? ?擴展接口是多個接口的集合。要實現擴展接口,需要實現多個接口。

? ?實現類型是把接口實現了,而擴展接口并沒有把接口實現,它只是多個接口的集合。

3.?在io包中,io.Reader的擴展接口實現類型都有哪些? (提升對io包的了解程度)

? ??io.Reader的擴展接口有下面幾種:

(1)?io.ReadWriter:包含字節序列讀取方法Read,和寫入方法Write。

(2)?io.ReadCloser:包含字節序列讀取方法Read,和關閉方法Close。Close用于關閉數據讀寫的通路。這個接口是io.Reader和io.Closer的組合。

(3)?io.ReadWriteCloser:io.Reader、io.Write 和io.Closer的組合。

(4)?io.ReadSeeker:可以根據給定的偏移量去尋找新的位置,作為下一次讀的起始索引。包含了尋找讀寫位置的基本方法Seek。io.Reader 和io.Seeker的組合。

(5)?io.ReadWriteSeeker:io.Reader、io.Writer和io.Seeker的組合。

? ?io.Reader接口的實現類型有下面幾種:

(1)?*io.LimitedReader:方法Read返回的總數據量會受到限制,無論被調用多少次。

(2)?*io.SectionReader:Read方法只能夠讀取原始數據中的某一個部分。與切片類似,只暴露在窗口之中的數據。

(3)?*io.teeReader:接受io.Reader和io.Writer兩個類型的參數,把Reader讀到的數據,通過字節切片中轉的方式,寫入io.Writer處。通常使用在數據流的處理中,比如計算下載速度。

(4)?*io.multiReader:接受多個io.Reader類型的參數,并從中順序地讀取數據。

(5)?*io.pipe:同步內存管道的核心實現

(6) * io.PipeReader:同步內存管道的讀取端

4.?io包中的接口都有哪些?

(1) 核心接口:io.Reader、io.Writer和io.Closer

(2)?io.ByteReader:讀取一個單一的字節。 strings.Reader和bytes.Buffer 是它的實現類型。

? ? ?io.RuneReader:讀取一個單一的Unicode 字符。strings.Reader和bytes.Buffer 是其實現類型

? ? ?io.ByteScanner:讀取和讀回退單個字節

? ? ?io.RuneScanner:讀取和讀回退單個Unicode 字符

? ? ?io.ReaderAt:只讀取數據,不修改已讀計數的值。

? ? ?io.ReaderFrom:從一個 Reader 中讀取數據

? ? ?io.WriteTo:將數據寫入到一個 Writer 中

? ? ?io.ReadWriter:讀和寫,?*io.pipe 是其實現類型。

? ? ?io.ReadWriteCloser:讀寫和關閉管道,net包有它的實現類型。

? ? ?io.ByteWriter和io.WriterAt:功能和上面對應。實現類型是 *os.File

? ? ?io.Seeker:尋找并設定下一次讀取或寫入時的起始索引位置。strings.Reader和io.SectionReader都是其實現類型。

? ??io.Closer:關閉管道。io.PipeReader和io.PipeWriter 是其實現類型。

(3) io包中的簡單接口共有 11 個。讀取操作相關的5 個,寫入操作相關的 4 個,關閉操作有關的1 個,讀寫位置設定相關的一個。此外,還包含了 9 個基于這些簡單接口的擴展接口。

二、bufio包中的數據類型

1.?bufio 包的程序實體,是在包裝簡單 I/O 接口類型值的基礎上,添加了緩沖區

2.?bufio包中的數據類型主要有:(1) Reader (2) Scanner (3) Writer 和 ReadWriter。

3.?bufio.Reader類型值中的緩沖區起著怎樣的作用?

????????Reader值會預先從底層讀取器里讀出一部分數據,暫存于緩沖區之中。當Reader值下次讀取數據時,先從緩沖區中讀取。 減少了底層讀取器的使用次數,降低讀取的執行時間。?

????????雖然,讀取時會增加填充緩沖區的操作,但從總體上看,平均執行時間會有大幅度的縮短。

4. bufio.Reader類型通過私有的 fill方法 來整理緩沖區,把已讀的空間騰出來,提供給底層讀取器存放數據。

? ? 整理方法就是把 [已讀計數, 已寫計數) 范圍內的數據往最前面搬運,如下圖所示:

5.?bufio.Reader類型讀取方法分別有哪些?

(1)?Peek方法:讀取緩沖區中的n個未讀字節,n大于緩沖區長度的話,轉而直接從底層讀取器中讀出數據。

??????會從已讀計數代表的索引位置開始讀,讀完不更改已讀計數。?

(2)?Read方法:其他和Peek方法一樣,但會更改已讀計數。?

(3)?ReadSlice方法:持續地讀取數據,直至遇到調用方給定的分隔符為止。

? ? ?如果緩沖區滿了仍然找不到分隔符,會把整個緩沖區作為第一個結果值,緩沖區已滿錯誤作為第二個結果值 返回。

(4)?ReadBytes方法: 其他和ReadSlice方法一樣,但緩沖區滿了仍然找不到分隔符的話,會再次調用ReadSlice方法,整理緩沖區之后繼續從底層讀取器中讀出數據,直至少找到分隔符或者讀完全部數據。

6.?內容泄露:Peek方法、ReadSlice方法和ReadLine方法都有可能會造成內容泄露,因為他們都是返回直接基于緩沖區的字節切片。 只有Read方法不會內容泄露。

三、使用os包中的API

1.?os代碼包中的 API,是對操作系統的某方面功能的高層次抽象,使我們可以用統一的方式,操縱不同的操作系統。

? ??最有代表性的就是數據類型 os.File,它實現了io包3 個核心接口io.Reader、io.Writer和io.Closer,3 個簡單接口,io.ReaderAt、io.Seeker和io.WriterAt,以及9 個擴展接口中的 7 個。

? ? 所以除 文本文件、二進制文件、壓縮文件、目錄這些常見的形式之外,還有符號鏈接、各種物理設備、命名管道,以及套接字(socket)都可以被視為文件。

2.?怎樣才能獲得一個os.File類型的指針值(File值)??

(1)?os.Create函數:根據給定的路徑創建一個新的文件。?

? ? ? 會返回一個File值和一個錯誤值。可以通過File值進行讀寫,路徑不存在的話會返回錯誤。

(2) os.Open函數:打開一個文件并返回包裝了該文件的File值。

? ? ? 只能從該File值中讀取內容,而不能寫入內容。

(3)?os.NewFile函數:依據已經存在的文件描述符,新建包裝了該文件的File值。

(4)?os.OpenFile函數:新建或打開文件。

? ? ?可讀可寫。函數有 3 個參數,為name(文件路徑)、flag(操作模式)和perm(權限模式)。

? ? ?可以視為這是基礎函數,上面3個函數只是這個基礎函數的參數組合。

3.?文件描述符,作為某個文件的一個標識存在。由 I/O 相關的系統調用返回,是很小的非負整數。

? ??任何文件的I/O 操作都需要這個文件描述符,它被存儲在File值中。

4.?File值的操作模式都有哪些?

? ??os.O_APPEND:追加模式寫入內容。

????os.O_CREATE:路徑不存在時創建文件。

? ? os.O_SYNC:在打開的文件上實施同步 I/O,保證讀寫的內容總會與硬盤上的數據同步。

? ??os.O_TRUNC:文件已存在時清空文件內容。

? ? 多個操作模式可以通過按位或操作符 " | "?組合起來的。

5. File值的權限模式都有哪些?

? ??權限模式參數 是uint32類型的再定義類型,包含了 32 個比特位,每個比特位都有特定含義:

(1)?最高比特位,1 代表 目錄。

(2)?第 26 個比特位,1代表?命名管道

(3)?最低的 9 個比特位才用于文件的權限,分別是 文件所有者、用戶組、其他用戶 對該文件的訪問權限(讀、寫和執行)。

四、訪問網絡服務

1. 進程間通信,稱為 IPC。主要方法包括:系統信號(signal)、管道(pipe)、套接字(socket)、文件鎖、消息隊列、信號量(semaphore)等。 socket 是最為通用和靈活的一種。

2. socket實例相關的API,是由一個名為 socket系統調用 代表的,它是連接應用程序和操作系統內核的橋梁。

? ??syscall代碼包中,有一個與這個 socket系統調用 相對應的函數。函數本身是平臺不相關的。在其底層,Go 為每個操作系統都做了適配,所以無論在哪個平臺上總是有效的。

? ??net代碼包中的很多程序實體,都會直接或間接地使用到syscall.Socket函數,比如net.Dial函數

3.?net.Dial函數的第一個參數network有哪些可選值?

(1) TCP、TCP4、TCP6:代表 TCP 協議,自適應、第四版、第六版

(2)?UDP、UDP4、UDP6:代表 UDP 協議,自適應、第四版、第六版

(3)?unix、unixgram、unixpacket:代表 Unix 通信域下的內部 socket 協議,socket 類型分別為SOCK_STREAM、SOCK_DGRAM、SOCK_SEQPACKET。

4.?有消息邊界,是指內核程序在發送或接收數據時,是以消息為單位的。

? ??有邏輯連接,是指通信雙方在收發數據之前必須先建立網絡連接

5. TCP 沒有消息邊界,有邏輯連接。 好處:保證可靠性,有序,雙向傳輸。壞處:速度慢。

? ? UDP 有消息邊界,沒有邏輯連接。好處:速度快。壞處:不保證可靠,無需,只能單向傳輸。

6.?net.DialTimeout函數 調用時給定的超時時間意味著什么?

? ?給定的超時時間,意味著函數為網絡建立連接,可以等待的最長時間。

? ?調用net.DialTimeout函數之后,時間主要花費在 “解析參數network和address的值”,以及“創建 socket 實例并建立網絡連接”這兩件事情上。

五、基于HTTP協議的網絡服務

1. net/http代碼包 可以使用 基于http協議的網絡服務。比如?http.Get函數。

? ? 實例:? resp, err := http.Get(url)? ? 返回兩個值:resp 和?err

? ? resp:數據類型是*http.Response,響應內容的結構體。

? ? err:數據類型是error,創建、發送請求、接收和解析、響應 全過程中,可能發生的錯誤。

2.?http.Get函數

? ? http.Get函數會在內部使用?缺省HTTP客戶端,它是 net/http包中的公開變量DefaultClient代表的,其類型是 *http.Client, 它是開箱即用的。

3.?http.Client類型中的 Transport字段?代表著什么?

(1)?Transport字段 的數據類型是?*http.Transport,會在內部使用net.Dialer類型值,實現 連接 和 超時 的功能。

(2)?http.Transport類型的值(以下簡稱Transport值)會對每一個網絡服務的空閑連接的總數做出限定。 一個網絡服務由網絡地址、網絡協議、代理 三方面來鑒定。

? ? ?在默認情況下,空閑連接總數最大為100,而每個網絡服務的最大空閑連接數為2。

(3)?*http.Transport 是?http.RoundTripper接口 的實現類型。RoundTripper 內部有一個DefaultTransport的缺省值。 前面提到的?缺省HTTP客戶端?DefaultClient ,其實也就是使用這個DefaultTransport。

(4) 總的來說 Transport字段代表著:向網絡服務發送 HTTP 請求,并從網絡服務接收 HTTP 響應的整個操作過程。

4.?http.Server類型的ListenAndServe方法都做了哪些事情?

(1) 對一個基于 TCP 協議的網絡地址進行監聽(net.Listen),并對接收到的 HTTP 請求進行處理。

(2)?默認開啟針對網絡連接的存活探測機制,以保證連接是持久的。

(3)?該方法會一直執行,直到有嚴重的錯誤發生或者被外界關掉。

5.?net.Listen函數都做了哪些事情?

(1)?解析參數值中網絡地址包含的 IP 地址端口號

(2)?根據給定的網絡協議,確定監聽的方法,并開始進行監聽。

6.?http.Server類型的Serve方法是怎樣接受和處理 HTTP 請求的?

(1) listen之后,進入一個for循環。

(2) for循環中,Accept方法會被不斷地調用,該方法返回兩個值:

? ? ?net.Conn類型:代表包含了新到來的 HTTP 請求的網絡連接

?????error類型:代表是否發生了錯誤。暫時性的錯誤的話for會繼續執行,否則會for循環都會被終止

(3) 把?net.Conn類型的結果值包裝成一個*http.conn類型,并啟用新的 goroutine ,去調用這個conn值的serve方法,來對當前的 HTTP 請求進行處理。

六、程序性能分析基礎

1.?性能分析 API 在這三個代碼包中:

(1) runtime/pprof

(2) net/http/pprof

(3) runtime/trace

2.?概要文件(Profile)

? ?runtime 代碼包中包含更底層的 API,用來收集程序運行過程中的一些關鍵指標,并生成概要文件,提供分析使用。

? ??go test 命令也可以在測試完成后生成?概要文件(Profile)。

3.?概要文件采樣時刻的內容

? ? ? 分析程序性能的概要文件有CPU、內存、阻塞三種概要文件。文件里每段概要信息都記錄著,某個采樣時刻的內容分別是:

(1) CPU 概要文件:CPU 上正在執行的 Go 代碼。

(2) 內存概要文件:內存的使用情況,已分配和已釋放的字節數量和對象數量。

(3) 阻塞概要文件:goroutine 阻塞事件

4.?概要文件內容格式

? ? 這些概要文件是以二進制存儲的,是通過 protocol buffers 生成的二進制字節流。

? ? 可以使用?go tool pprof 工具查看。

5.?怎樣讓程序對 CPU 概要信息進行采樣?

(1) 進行采樣調用StartCPUProfile函數;停止采樣調用StopCPUProfile函數。

(2)?StartCPUProfile函數,會設定 CPU 概要信息的采樣頻率,并在單獨的 goroutine 中進行收集和輸出。 CPU采樣頻率總是固定100赫茲的,經過大量實驗證明最優。

(3)?StopCPUProfile函數,會采樣頻率設為0,采樣工作停止。

6.?怎樣設定內存概要信息的采樣頻率?

(1)?為 runtime.MemProfileRate變量賦值即可。?含義是,每分配多少個字節,就對堆內存的使用情況進行一次采樣。缺省值是512 KB。

(2) 越早設定越好,避免運行時造成不良影響。最好只在main函數的開始處設定一次。

(3)?想獲取內存概要信息的時候, 調用WriteHeapProfile函數。但它并非實時數據,是在最近一次的內存垃圾收集工作完成時產生的。

(4)?可以調用runtime.ReadMemStats函數,獲得實時數據。不過該函數會引起 Go 語言調度器的短暫停頓。

7.?怎樣獲取到阻塞概要信息?

(1) 調用runtime包中的SetBlockProfileRate函數,可對阻塞概要信息的采樣頻率進行設定。

(2) 函數有一個名叫rate的參數,int類型。含義是,只要發現一個阻塞事件的持續時間達到了多少納秒,就對其進行采樣。

(3) 在runtime包中,有一個名叫blockprofilerate的私有變量,uint64類型。含義是,只要發現一個阻塞事件的持續時間跨越了多少個 CPU 時鐘周期,就對其進行采樣。和(2)的區別僅僅在于單位不同。?

(4)?缺省值是0,所以默認情況下并不會記錄任何阻塞事件。

(5)?需要獲取阻塞概要信息的時候,做兩步操作:

? ? 調用runtime/pprof包中的 Lookup函數 并傳入參數值"block",得到*runtime/pprof.Profile類型的值? ? ?

? ? 調用Profile值的 WriteTo方法,把概要信息寫進指定的寫入器中。

8.?runtime/pprof.Lookup函數的正確調用方式是什么?

(1)?Lookup函數的功能是,提供 給定的名稱?相對應的概要信息。

(2)?給定的名稱 包括:

goroutine:收集當前正在使用的所有 goroutine 堆棧跟蹤信息。會引起 Go 調度器的短暫停頓。

heap:收集與堆內存的分配和釋放有關的采樣信息。也就是前面的內存概要信息。

allocs:與heap大致一樣,但?allocs 收集到的是已分配空間(已分配不管有否釋放),heap是在用空間(已分配未釋放)。

threadcreate:收集堆棧跟蹤信息,描繪出代碼調用鏈。

block:在代碼同步競爭中被阻塞的代碼的堆棧跟蹤信息。就是前面的阻塞概要信息。

mutex:在代碼同步競爭中,獲得過執行的代碼的堆棧跟蹤信息。

9.?如何為基于 HTTP 協議的網絡服務添加性能分析接口?

(1)?在程序中導入net/http/pprof代碼包。

? ? ?import _ "net/http/pprof"

(2)?啟動網絡服務并開始監聽。

? ? ?log.Println(http.ListenAndServe("localhost:8082", nil))

(3)?在瀏覽器中訪問? http://localhost:8082/debug/pprof? 看到一個簡約的網頁

(4)?在/debug/pprof/ 這個URL路徑下還有很多可用的子路徑,包括:profile,trace,allocs、block、goroutine、heap、mutex、threadcreate。

(5) 返回二進制內容時,需要使用??go tool pprof 工具去查看。

? ? go tool pprof http://localhost:6060/debug/pprof/profile?seconds=60

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/13402.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/13402.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/13402.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

瀏覽器插件Video Speed Controller(視頻倍速播放),與網頁自身快捷鍵沖突/重復/疊加的解決辦法

瀏覽器插件Video Speed Controller(視頻倍速播放),與網站自身快捷鍵沖突/重復/疊加的解決辦法 插件介紹問題曾今嘗試的辦法今日發現插件列表中打開Video Speed Controller的設置設置頁面翻到下面,打開實驗性功能。將需要屏蔽的原網…

網絡工程師----第三十一天

DNS: DNS含義:DNS 是 Domain Name System(域名解析系統) 端口號:DNS為53(UDP) 域名的層次結構: 域名的分級: 域名服務器: 域名解析過程: 遞歸查…

PHP xdebug

使用場景 一臺MAC上安裝了phpstorm,虛擬機安裝了對應的web程序,需要調試。 坑點,網上教程太多,不如看官網,需要按照xdebug版本來配置php.ini https://www.jetbrains.com/help/phpstorm/2023.3/configuring-xdebug.htm…

【Java】HOT100+代碼隨想錄 動態規劃(上)背包問題

目錄 理論基礎 一、基礎題目 LeetCode509:斐波那契數 LeetCode70:爬樓梯 LeetCode746:使用最小花費爬樓梯 LeetCode62:不同路徑 LeetCode63:不同路徑ii LeetCode343:整數拆分 LeetCode96:不…

vue uniapp 小程序 判斷日期是今天(顯示時分秒)、昨天、本周的周幾、超出本周顯示年月日

效果圖: util.js /*** 轉換時間*/ const messageFormat (datetime) >{ let result "";let currentTime new Date();if(isToday(datetime)){result datetime.substring(11,16);}else if(isYesterday(datetime)){result "昨天";}else if(…

分層解耦-三層架構

分層解耦-三層架構 Controller:控制層,接收前端發送的請求,對請求進行處理,并響應數據 service:業務邏輯層,處理具體的業務邏輯 dao:數據訪問層(持久層),負…

python爬蟲[簡易版]

python爬數據[簡易版] 對于每個網站的爬的原理基本是一樣的,但是具體的代碼寫法的區別就在于爬的數據中解析出想要的數據格式: 以爬取有道詞典中的圖片為例: 第一步:打開網站,分析圖片的數據源來自哪里, https://dict-subsidiary.youdao.com/home/content?invalid&pre…

操作系統磁盤管理類問題

例題:在磁盤上存儲數據的排列方式會影響1/0服務的總時間。假設每個磁道被劃分成10個物理塊,每個物理塊存放1個邏輯記錄。邏輯記錄R1,R2....R10存放在同一個磁道上,記錄的排列順序如下表所示: 假定磁盤的旋轉速度為10ms/周&#xf…

VMware虛擬機-安裝程序無法自動安裝virtual machine......_windows server 2008 R2

系統版本:windows server 2008 R2 問題-安裝程序無法自動安裝virtual machine… 在使用虛擬機安裝windows server 2008 R2系統中,安裝VMware Tools工具安祖啊寄給你失敗,提示安裝程序無法自動安裝virtual machine…,必須手動安裝…

從源頭到洞察:大數據時代的數據提取與分析實戰指南

隨著科技的飛速發展,大數據已經成為現代社會的核心驅動力之一。從商業決策到科學研究,從政策制定到個人生活,數據無處不在,影響著我們的每一個決策。然而,如何從海量的數據中提取有價值的信息,并轉化為深刻…

List類

什么是 List 在集合框架中, List 是一個接口,繼承自 Collection 。 Collection 也是一個接口 ,該接口中規范了后序容器中常用的一些方法,具體如下所示: List 中提供了好的方法,具體如下: List…

Conda 常用命令大全

Conda 常用命令大全 配置源conda配置清華源pip配置清華源pip配置阿里源 環境管理創建一個新的虛擬環境列出虛擬環境激活虛擬環境退出虛擬環境刪除虛擬環境復制某個虛擬環境 conda包管理列出全部包安裝包卸載包 pip包管理列出全部包安裝包卸載包 其他命令查詢 conda 版本查看環境…

python發票真偽查驗開發文檔、票據OCR、數電票查驗

想象一下,只需一行行簡潔的代碼,復雜繁瑣的發票審核工作瞬間變得井然有序。翔云發票查驗開發文檔詳盡易懂,即便是Python新手也能迅速上手,搭建起自己的發票真偽查驗系統。無論是紙質發票的掃描圖像,還是電子發票的數據…

C語言詳解:數組指針

數組指針是指針 int* p[10] 這是指針數組的寫法 ,因為【】的優先級比*高, 所以為了解決優先級問題,加() int(* p)[10]&arr;//數組的地址要存起來 說明p是指針(首先與*結合)&#xff0c…

哈希表法快速求解最長連續序列 | 力扣128題詳細解析

?????? 歡迎來到我的博客。希望您能在這里找到既有價值又有趣的內容,和我一起探索、學習和成長。歡迎評論區暢所欲言、享受知識的樂趣! 推薦:數據分析螺絲釘的首頁 格物致知 終身學習 期待您的關注 導航: LeetCode解鎖100…

Oracle 數據庫 19c 選件和管理包 英文技術文檔

都是英文的,點擊鏈接可單獨下載。點這里批量下載。 Database Options: 數據庫選件或管理包數據表技術白皮書MultitenantData Sheet(12c)White PaperReal Application ClustersData Sheet(12c)White PaperActive Data GuardData Sheet(沒找到)White Pap…

關于電源3(整流濾波電路)

整流濾波電路 框圖 一共有四種整流電路 以下是自己參考別人的文章https://blog.csdn.net/zhuguanlin121/article/details/130653498?ops_request_misc%257B%2522request%255Fid%2522%253A%2522171582622316800215096518%2522%252C%2522scm%2522%253A%252220140713.130102334…

jenkins配置不同版本nodeJS,保姆級叫你配置

問題描述:公司jenkins被改了nodejs版本適配其他項目導致以前的項目構建失敗,原因就是nodejs版本太高或太低導致,這里教大家不去更改服務器默認版本,當需要特殊版本直接在jenkins里配置即可。 過程 1、安裝nodeJS插件 1.1點擊管…

Linux中的nproc命令

2024年5月15日,周三上午 nproc 是一個在類 Unix 系統中使用的命令行實用程序,用于返回系統上可用的處理器核心數量。這個數字通常比物理 CPU 核心的數量要少,因為它可能排除了超線程核心或熱插拔核心。nproc 命令讀取 /proc/cpuinfo 文件來獲…

怎么把照片變小做頭像?多種方法教你圖片改尺寸

現在在社交媒體平臺或者是社交軟件上,我們經常會去更改頭像來展示自己,但是有時候我們拍攝的照片太大無法直接用作頭像,這時候就需要去修改圖片尺寸,將圖片改大小到合適的數值才能使用,那么如何快速的將圖片改大小呢&a…