Maison > Article > développement back-end > Discutez de la façon dont Golang implémente la fonction tail
Golang est un langage de programmation moderne de plus en plus populaire et soutenu par le public. Grâce à ses fonctionnalités efficaces et stables, il peut non seulement répondre aux besoins des développeurs en matière de hautes performances et de faible consommation de ressources, mais également être capable de mettre en œuvre une variété de fonctions.
Dans cet article, nous explorerons comment Golang implémente la fonction tail, qui surveille les modifications dans un fichier et affiche les dernières lignes d'informations du fichier.
Idées d'implémentation
Avant de commencer à implémenter la fonction tail, nous devons d'abord comprendre l'idée de base de sa mise en œuvre. En général, nous devons implémenter les fonctions suivantes :
Implémenter l'analyse
Tout d'abord, nous devons introduire le package os pour lire et fermer le fichier. Nous devons également définir un type de structure pour représenter la fonctionnalité de queue.
package main import ( "fmt" "os" ) type Tail struct { File *os.File // 文件指针 Size int64 // 文件大小 Cursor int64 // 文件指针所在位置 Rows int // 输出行数 }
Nous avons défini un type de structure Tail, dans lequel le champ File est le pointeur de fichier, le champ Size est la taille du fichier, le champ Cursor représente la position actuelle du pointeur de fichier et le champ Rows représente le nombre de lignes de sortie. .
Ensuite, nous devons implémenter la fonction d'ouverture de fichiers. Dans Golang, la lecture du contenu des fichiers peut être implémentée via le package os. Après avoir ouvert le fichier, nous pouvons obtenir les informations sur le fichier via la fonction os.Stat(), y compris la taille du fichier, la position du pointeur de fichier, etc. Nous devons également penser à positionner le pointeur de fichier à la fin du fichier.
func (t *Tail) OpenFile(path string, rows int) error { var err error // 打开文件 t.File, err = os.Open(path) if err != nil { fmt.Printf("open file %s err: %s\n", path, err.Error()) return err } // 获取文件信息 fi, err := t.File.Stat() if err != nil { fmt.Printf("get file info err:%s", err.Error()) return err } // 获取文件大小 t.Size = fi.Size() // 将文件指针定位到文件末尾 _, err = t.File.Seek(0, os.SEEK_END) if err != nil { fmt.Printf("move file pointer failed. err:%s\n", err.Error()) return err } // 设置输出行数 t.Rows = rows return nil }
Dans le code, nous ouvrons d'abord le fichier via la fonction os.Open() et obtenons les informations sur le fichier via la fonction os.Stat(). Ensuite, nous utilisons la fonction os.Seek() pour pointer le pointeur de fichier vers la fin du fichier afin de garantir que le programme lit les dernières informations sur le fichier.
Selon le nombre de lignes de sortie saisies par l'utilisateur, nous enregistrons les informations sur le numéro de ligne. Il convient de noter ici que nous devons diviser le nombre de lignes par 2, car une ligne de certains fichiers peut être composée de plusieurs lignes, et l'implémentation spécifique est laissée au lecteur pour y réfléchir.
Ensuite, nous implémentons le suivi des changements de sortie, implémenté dans goroutine.
func (t *Tail) Follow() { defer t.File.Close() // 开始监视文件变化 for { fi, err := t.File.Stat() if err != nil { fmt.Printf("get file info error: %s\n", err.Error()) return } // 如果指针超过文件大小,将指针移到文件末尾 if t.Cursor > fi.Size() { _, err = t.File.Seek(0, os.SEEK_END) if err != nil { fmt.Printf("move file pointer failed. err:%s\n", err.Error()) return } t.Cursor = fi.Size() } // 读取差异部分的内容,并输出 if fi.Size() > t.Cursor { data := make([]byte, fi.Size()-t.Cursor) _, err = t.File.ReadAt(data, t.Cursor) if err != nil { fmt.Printf("read file failed. err:%s\n", err.Error()) return } lines := strings.Split(string(data), "\n") for i := len(lines) - t.Rows/2; i < len(lines); i++ { fmt.Println(lines[i]) } t.Cursor += int64(len(data)) fmt.Printf("Cursor:%d\n", t.Cursor) } time.Sleep(1 * time.Second) } }
Dans goroutine, nous obtenons des informations sur le fichier via la fonction os.File.Stat() et vérifions si la taille du fichier a changé. Si la taille du fichier change, nous lisons le contenu de la partie différence, le publions et mettons à jour la position du pointeur de fichier.
Nous lisons le contenu du fichier en lignes et affichons uniquement les dernières lignes afin d'éviter le problème des nouvelles lignes dépassant la plage de sortie.
En fait, démarrer une goroutine peut surveiller les modifications de fichiers, et un changement de taille de fichier signifie que le contenu du fichier a changé. À ce stade, nous pouvons utiliser la fonction os.File.ReadAt() pour lire le contenu de la différence. , puis sortie.
Enfin, nous devons implémenter l'impression des journaux d'erreurs.
func main() { // 构造 Tail 结构体 t := &Tail{} // 打开文件 err := t.OpenFile("test.log", 20) if err != nil { return } // 监听文件变化 fmt.Println("start following...") t.Follow() fmt.Println("tail finish.") }
Dans la fonction main(), nous ouvrons d'abord le fichier via la fonction OpenFile(), puis surveillons les modifications du fichier via la fonction Follow() pour implémenter la fonction tail. Ici, nous surveillons les modifications dans le fichier et générons en permanence les dernières lignes d'informations du fichier jusqu'à ce que le fichier soit fermé ou que le programme s'arrête.
Conclusion
Ce qui précède explique comment Golang implémente la fonction tail. C’est simple à mettre en œuvre et pratique à la fois. Dans le développement réel, l'optimisation correspondante peut être effectuée en fonction de besoins spécifiques, tels que la lecture de plus de lignes, la sortie vers un fichier journal spécifié, etc. Cette implémentation peut aider les développeurs à mieux surveiller les modifications des fichiers et à mieux répondre aux besoins de développement.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!