<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Inhere</title>
    <description>The latest articles on Forem by Inhere (@inhere).</description>
    <link>https://forem.com/inhere</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F189337%2F89b81983-1573-41be-a1d8-c8db45ba5436.jpeg</url>
      <title>Forem: Inhere</title>
      <link>https://forem.com/inhere</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/inhere"/>
    <language>en</language>
    <item>
      <title>gookit/goutil v0.7.2 Released: Enhanced Features &amp; Fixes for an Improved Development Experience</title>
      <dc:creator>Inhere</dc:creator>
      <pubDate>Thu, 20 Nov 2025 14:36:14 +0000</pubDate>
      <link>https://forem.com/inhere/gookitgoutil-v072-released-enhanced-features-fixes-for-an-improved-development-experience-3d06</link>
      <guid>https://forem.com/inhere/gookitgoutil-v072-released-enhanced-features-fixes-for-an-improved-development-experience-3d06</guid>
      <description>&lt;p&gt;We're excited to announce the release of &lt;code&gt;gookit/goutil&lt;/code&gt; v0.7.2! This version brings numerous new features, optimizations, and bug fixes, further enhancing the stability and usability of this Go utility library. &lt;br&gt;
This update covers multiple modules, including math utilities, string processing, filesystem operations, and command-line flag handling, aiming to provide developers with a richer and more efficient toolkit.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Project Homepage: &lt;a href="https://github.com/gookit/goutil" rel="noopener noreferrer"&gt;https://github.com/gookit/goutil&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Full Changelog: &lt;a href="https://github.com/gookit/goutil/releases/tag/v0.7.2" rel="noopener noreferrer"&gt;v0.7.2 Release Notes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Full documentation: &lt;a href="https://zread.ai/gookit/goutil" rel="noopener noreferrer"&gt;https://zread.ai/gookit/goutil&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🛠️ Key Bug Fixes
&lt;/h2&gt;

&lt;p&gt;This version fixes several key issues to ensure the stable operation of the library:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;ccolor module&lt;/strong&gt;: Fixed the issue where the &lt;code&gt;NO_COLOR&lt;/code&gt; environment variable was not working correctly during printing, improving the compatibility of color output.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;cflag module&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  Fixed a &lt;code&gt;capp&lt;/code&gt; runtime error that occurred when parsing global flags.&lt;/li&gt;
&lt;li&gt;  Fixed the issue where the &lt;code&gt;OnAppFlagParsed&lt;/code&gt; event was not triggered when no command was input, ensuring the integrity of the event handling logic.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  ✨ New Feature Highlights
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Math Utilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Added the &lt;code&gt;IsInteger&lt;/code&gt; function for &lt;strong&gt;strictly checking if a value is of an integer type&lt;/strong&gt; (e.g., &lt;code&gt;int(x)&lt;/code&gt;, &lt;code&gt;uint(x)&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  Added &lt;code&gt;StrictInt&lt;/code&gt; and &lt;code&gt;StrictUint&lt;/code&gt; conversion functions for stricter integer type conversions.&lt;/li&gt;
&lt;li&gt;  Added the &lt;code&gt;FormatBytes&lt;/code&gt; function to format byte sizes into &lt;strong&gt;human-readable strings&lt;/strong&gt; (e.g., "1.2 MB"), convenient for log output and UI display.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  String Utilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Added the &lt;code&gt;NumVersion&lt;/code&gt; function to quickly extract the numeric part from a version string.&lt;/li&gt;
&lt;li&gt;  Added the &lt;code&gt;ReplaceVars&lt;/code&gt; function to support quick rendering of strings containing &lt;code&gt;{var}&lt;/code&gt; placeholders, simplifying template replacement operations.&lt;/li&gt;
&lt;li&gt;  Added &lt;code&gt;IsUpper&lt;/code&gt; and &lt;code&gt;IsLower&lt;/code&gt; functions to check if a string is entirely uppercase or lowercase.&lt;/li&gt;
&lt;li&gt;  Added &lt;code&gt;IsUint&lt;/code&gt; and &lt;code&gt;IsPositiveNum&lt;/code&gt; functions to enhance string numeric validation capabilities.&lt;/li&gt;
&lt;li&gt;  Added &lt;code&gt;BaseConvInt&lt;/code&gt; and &lt;code&gt;BaseConvIntByTpl&lt;/code&gt; functions to support integer conversion between different bases.&lt;/li&gt;
&lt;li&gt;  Added the &lt;code&gt;ContainsByteOne&lt;/code&gt; function to check if a string contains any of the specified bytes.&lt;/li&gt;
&lt;li&gt;  Optimized the &lt;code&gt;MTimeBaseID&lt;/code&gt; function, which now supports bases greater than 36.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Filesystem Utilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Added the &lt;code&gt;EnsureDir&lt;/code&gt; function to ensure a directory exists (creates it if it doesn't).&lt;/li&gt;
&lt;li&gt;  Added &lt;code&gt;HomeDir&lt;/code&gt;/&lt;code&gt;UserHomeDir&lt;/code&gt; functions to get the user's home directory path.&lt;/li&gt;
&lt;li&gt;  Added &lt;code&gt;CreateSymlink&lt;/code&gt; and &lt;code&gt;IsSymlink&lt;/code&gt; functions to support the creation and detection of symbolic links.&lt;/li&gt;
&lt;li&gt;  Added &lt;code&gt;FindAllInParentDirs&lt;/code&gt;, &lt;code&gt;FindOneInParentDirs&lt;/code&gt;, and &lt;code&gt;FindNameInParentDirs&lt;/code&gt; functions to support &lt;strong&gt;finding files in parent directories&lt;/strong&gt;, simplifying the location of project configuration files.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Array/Slice Utilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Added the &lt;code&gt;ToMap&lt;/code&gt; function to convert a list (slice) to a map.&lt;/li&gt;
&lt;li&gt;  Added the &lt;code&gt;Map1&lt;/code&gt; function to convert a list to a new list (similar to a map operation).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Map Utilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Added the &lt;code&gt;AppendSMap&lt;/code&gt; function for merging string maps.&lt;/li&gt;
&lt;li&gt;  Added the &lt;code&gt;AliasesNames&lt;/code&gt; function for handling alias names.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Testing Utilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Added the &lt;code&gt;assert.StrContainsAll&lt;/code&gt; assertion function to check if a string contains all specified substrings.&lt;/li&gt;
&lt;li&gt;  Added the &lt;code&gt;testutil.SafeBuffer&lt;/code&gt; type, a &lt;strong&gt;thread-safe buffer&lt;/strong&gt; designed for concurrent testing scenarios.&lt;/li&gt;
&lt;li&gt;  Enhanced &lt;code&gt;testutil.EchoServer&lt;/code&gt;, which now supports responding with 404, 405, 500, or custom status codes, facilitating the testing of HTTP client error handling logic.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Command-line Utilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  The &lt;code&gt;cflag&lt;/code&gt; module has a new &lt;code&gt;HelpOnEmptyArgs&lt;/code&gt; configuration option to automatically display help information when no arguments are provided, improving user experience.&lt;/li&gt;
&lt;li&gt;  Optimized the rendering of help information.&lt;/li&gt;
&lt;li&gt;  Added support for setting aliases for &lt;code&gt;cflag/capp&lt;/code&gt; commands.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Time Utilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Added the &lt;code&gt;FormatDuration&lt;/code&gt; function to format time duration into a &lt;strong&gt;clock-like format&lt;/strong&gt; (e.g., "1h 23m 45s"), perfect for displaying performance statistics.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  ⚡ Performance Optimizations &amp;amp; Refactoring
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Optimized the common logic of the &lt;code&gt;ToStringWith&lt;/code&gt; function to improve conversion performance.&lt;/li&gt;
&lt;li&gt;  Refactored &lt;code&gt;cflag.App&lt;/code&gt; into the subpackage &lt;code&gt;capp.App&lt;/code&gt;, improving code organization.&lt;/li&gt;
&lt;li&gt;  Optimized the handling options logic in the &lt;code&gt;ToInt64With&lt;/code&gt; function to enhance conversion efficiency.&lt;/li&gt;
&lt;li&gt;  Split integer conversion related code into &lt;code&gt;conv2int.go&lt;/code&gt; and optimized the performance of all integer conversion related methods in &lt;code&gt;mathutil&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Updated the &lt;code&gt;VersionCompare&lt;/code&gt; function logic, fixing some comparison errors and improving the accuracy of version comparison.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;VarReplacer&lt;/code&gt; in &lt;code&gt;textutil&lt;/code&gt; now supports parsing variable names as environment variables, enhancing dynamic configuration capabilities.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🌐 Platform Compatibility &amp;amp; Development Workflow
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Added support for FreeBSD/Unix systems&lt;/strong&gt;, expanding the platform coverage of the &lt;code&gt;sysutil&lt;/code&gt; package.&lt;/li&gt;
&lt;li&gt;  Added comprehensive &lt;strong&gt;GitHub Copilot instructions&lt;/strong&gt; for gookit/goutil, optimizing the AI-assisted development workflow.&lt;/li&gt;
&lt;li&gt;  Upgraded the &lt;code&gt;github/codeql-action&lt;/code&gt; dependency from version 3 to 4, enhancing the security and capabilities of code analysis.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  📝 Other Updates
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Added a &lt;code&gt;ShowLen&lt;/code&gt; option for &lt;code&gt;dump&lt;/code&gt; output, allowing control over whether to display length information.&lt;/li&gt;
&lt;li&gt;  Updated the README generation CLI and related documentation, improving the project documentation generation process and templates.&lt;/li&gt;
&lt;li&gt;  Fixed unit test errors and unified the code style.&lt;/li&gt;
&lt;li&gt;  Updated some comments and code styles.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  📦 How to Update
&lt;/h2&gt;

&lt;p&gt;You can use the following command to get the latest version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/gookit/goutil@v0.7.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Migration &amp;amp; Compatibility Notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;cflag -&amp;gt; cflag/capp&lt;/code&gt; Subpackage Refactoring: &lt;code&gt;cflag.App&lt;/code&gt; has been refactored to &lt;code&gt;capp.App&lt;/code&gt;. If your code directly references &lt;code&gt;cflag.App&lt;/code&gt;, please adjust:

&lt;ul&gt;
&lt;li&gt;  Old: &lt;code&gt;import "github.com/gookit/goutil/cflag"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  New: &lt;code&gt;import "github.com/gookit/goutil/capp"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  And switch related types/calls to the App in the &lt;code&gt;capp&lt;/code&gt; package.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;TIP: This is a potential breaking change in this release, please check and update your references before upgrading.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;VersionCompare&lt;/code&gt; and some string/version-related logic have been optimized. If you rely on the edge-case behavior of the old logic (such as equality comparison or sorting), please run relevant unit tests to verify after upgrading.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example Snippets
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Using &lt;code&gt;mathutil.IsInteger / StrictInt&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/gookit/goutil/mathutil"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/gookit/goutil/testutil/assert"&lt;/span&gt;

&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;123&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mathutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;i64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mathutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StrictInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"42"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Does not allow string to integer conversion&lt;/span&gt;
&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;False&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Using &lt;code&gt;strutil.ReplaceVars&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/gookit/goutil/strutil"&lt;/span&gt;

&lt;span class="n"&gt;tpl&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Hello, {name}! Today is {day}."&lt;/span&gt;
&lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReplaceVars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tpl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Gopher"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"day"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;"Wednesday"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c"&gt;// Output: "Hello, Gopher! Today is Wednesday."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Using &lt;code&gt;fsutil.EnsureDir&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/gookit/goutil/fsutil"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fsutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnsureDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tmp/myapp/logs"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Handle error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🤝 Contributing
&lt;/h2&gt;

&lt;p&gt;We thank all contributors for their efforts in this release! If you find any issues or have feature suggestions, please feel free to open an issue at &lt;a href="https://github.com/gookit/goutil/issues" rel="noopener noreferrer"&gt;GitHub Issues&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  📖 More Information
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Project Homepage: &lt;a href="https://github.com/gookit/goutil" rel="noopener noreferrer"&gt;https://github.com/gookit/goutil&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Full Changelog: &lt;a href="https://github.com/gookit/goutil/releases/tag/v0.7.2" rel="noopener noreferrer"&gt;v0.7.2 Release Notes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Full documentation: &lt;a href="https://zread.ai/gookit/goutil" rel="noopener noreferrer"&gt;https://zread.ai/gookit/goutil&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enjoy the new features and improvements in v0.7.2&lt;/p&gt;

</description>
      <category>programming</category>
      <category>github</category>
      <category>development</category>
      <category>backend</category>
    </item>
    <item>
      <title>gookit/slog - release v0.5.8, Lightweight, configurable, extensible logging library</title>
      <dc:creator>Inhere</dc:creator>
      <pubDate>Thu, 01 May 2025 02:01:37 +0000</pubDate>
      <link>https://forem.com/inhere/gookitslog-release-v058-lightweight-configurable-extensible-logging-library-16ch</link>
      <guid>https://forem.com/inhere/gookitslog-release-v058-lightweight-configurable-extensible-logging-library-16ch</guid>
      <description>&lt;p&gt;We’re thrilled to announce the release of &lt;strong&gt;gookit/slog v0.5.8&lt;/strong&gt;, a significant update to the lightweight, configurable, and extensible logging library for Go. With this release, we’ve addressed critical bug fixes, introduced powerful new features, and refined the overall functionality to offer an even more reliable logging experience for developers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Github: &lt;a href="https://github.com/gookit/slog" rel="noopener noreferrer"&gt;https://github.com/gookit/slog&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Highlights of v0.5.8
&lt;/h4&gt;

&lt;h5&gt;
  
  
  🛠️ Bug Fixes
&lt;/h5&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Windows File Path Parsing Issue Resolved&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Fixed a bug where log file paths could encounter parsing errors on Windows systems. (&lt;a href="https://github.com/gookit/slog/commit/9e6939b11743dfd62c660227f626ccdf07615047" rel="noopener noreferrer"&gt;Commit&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Backup File Handling Improvement&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Resolved a problem where setting &lt;code&gt;BackupNum=0&lt;/code&gt; caused all old files to be removed.  (&lt;a href="https://github.com/gookit/slog/commit/183fb6af53baaa777dd3fd7395f765037af68056" rel="noopener noreferrer"&gt;Commit&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File Rotation Stability&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Fixed issues related to file rotation in short intervals, which previously caused conflicts and content overwrites.  (&lt;a href="https://github.com/gookit/slog/commit/e8e8d6f4bd548efee13c488e71b759563821fcc0" rel="noopener noreferrer"&gt;Commit&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Old File Matching Issue&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Resolved incorrect handling of file renaming (e.g., &lt;code&gt;error.log&lt;/code&gt; to &lt;code&gt;error.20250423_02.log&lt;/code&gt;). (&lt;a href="https://github.com/gookit/slog/commit/3d44bd2ef22c67e4d344865e75943e713a421c9e" rel="noopener noreferrer"&gt;Commit&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h5&gt;
  
  
  ✨ New Features
&lt;/h5&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced Logging Configuration&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Improved the configuration functions, making it easier to fine-tune logging behavior. (&lt;a href="https://github.com/gookit/slog/commit/ce6b6828b34d5ec9c607bf4615460a9a469bfa6a" rel="noopener noreferrer"&gt;Commit&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Top-Level &lt;code&gt;Log&lt;/code&gt; Function&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Introduced a &lt;code&gt;Log&lt;/code&gt; function at the package's top level for more streamlined usage.  (&lt;a href="https://github.com/gookit/slog/commit/581d3ba8955fe0f1eeb26bb97e14686c4be95981" rel="noopener noreferrer"&gt;Commit&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h5&gt;
  
  
  🔄 Updates and Improvements
&lt;/h5&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;WithRotateTimeString&lt;/code&gt; Function Added&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A new function to handle rotation time strings, along with corresponding tests. (&lt;a href="https://github.com/gookit/slog/commit/07105c60483cc1e9b758247e6f214c8976b3f2f5" rel="noopener noreferrer"&gt;Commit&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Refactored Clean Method&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The clean method in the &lt;code&gt;rotatefile&lt;/code&gt; handler now includes additional tests for compressing and cleaning files.(&lt;a href="https://github.com/gookit/slog/commit/5caffda6c8dc33ed97f91e4274b96e878be8191c" rel="noopener noreferrer"&gt;Commit&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved Debugging Logs&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Added a debug mode environment variable and more detailed log outputs for development purposes. (&lt;a href="https://github.com/gookit/slog/commit/ee1d5848b585783ca9a14e0b6de8cd1bb2d152d6" rel="noopener noreferrer"&gt;Commit&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimized Rotate File Logic&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Refactored the logic to ensure file extensions are always at the end and reduced lock ranges during write and rotation processes. (&lt;a href="https://github.com/gookit/slog/commit/afd01cc28cbaa8ce5ce7ea1e4346cf21079c3f74" rel="noopener noreferrer"&gt;Commit&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h5&gt;
  
  
  📦 Dependency Updates
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Updated &lt;code&gt;github.com/gookit/goutil&lt;/code&gt; to v0.6.18.
(&lt;a href="https://github.com/gookit/slog/pull/153" rel="noopener noreferrer"&gt;PR #153&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Updated &lt;code&gt;github.com/golang/glog&lt;/code&gt; from v1.1.1 to v1.2.4 for examples.
(&lt;a href="https://github.com/gookit/slog/pull/157" rel="noopener noreferrer"&gt;PR #157&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  🧪 Improved Test Coverage
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Added more unit test cases and internal test functions to ensure the stability and reliability of new features.  (&lt;a href="https://github.com/gookit/slog/commit/5b64610339e53fe5dc59a8c9b0fa72bca59a523c" rel="noopener noreferrer"&gt;Commit&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  Acknowledging New Contributors
&lt;/h4&gt;

&lt;p&gt;We’re excited to welcome two new contributors to the gookit/slog community:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;@ShyunnY&lt;/strong&gt; for their work on the &lt;code&gt;CallerFlagMode&lt;/code&gt; type alias. (&lt;a href="https://github.com/gookit/slog/pull/155" rel="noopener noreferrer"&gt;PR #155&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@knbr13&lt;/strong&gt; for updating the code to use &lt;code&gt;os.ReadFile&lt;/code&gt; instead of the deprecated &lt;code&gt;ioutil.ReadFile&lt;/code&gt;. (&lt;a href="https://github.com/gookit/slog/pull/158" rel="noopener noreferrer"&gt;PR #158&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  Full Changelog
&lt;/h4&gt;

&lt;p&gt;To explore all changes in detail, check out the &lt;a href="https://github.com/gookit/slog/compare/v0.5.7...v0.5.8" rel="noopener noreferrer"&gt;v0.5.8 changelog&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;This release represents a significant step forward in making &lt;code&gt;gookit/slog&lt;/code&gt; a more robust, flexible, and user-friendly logging solution for Go developers. We’re grateful for the contributions from the community and look forward to seeing how these changes will enhance your projects. &lt;/p&gt;

&lt;p&gt;Happy Logging!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>programming</category>
      <category>go</category>
      <category>github</category>
    </item>
    <item>
      <title>gookit/goutil - released v0.6.10, an extension library of common Go features</title>
      <dc:creator>Inhere</dc:creator>
      <pubDate>Wed, 05 Jul 2023 03:44:25 +0000</pubDate>
      <link>https://forem.com/inhere/gookitgoutil-released-v0610-an-extension-library-of-common-go-features-16ho</link>
      <guid>https://forem.com/inhere/gookitgoutil-released-v0610-an-extension-library-of-common-go-features-16ho</guid>
      <description>&lt;p&gt;&lt;code&gt;gookit/goutil&lt;/code&gt; An extended library of Go's common functionality. Contains: number, string, slice/array, Map, struct, reflection, text, file, error, time and date, test, CLI, command run, system information, formatting, common information acquisition, etc.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Github&lt;/strong&gt;: &lt;a href="https://github.com/gookit/goutil"&gt;https://github.com/gookit/goutil&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  v0.6.10 change log
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Full changelog &lt;a href="https://github.com/gookit/goutil/compare/v0.6.9...v0.6.10"&gt;v0.6.9...v0.6.10&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  ✨ New features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✨ feat: testutil - adds a new child package &lt;code&gt;fakeobj&lt;/code&gt; to create fake objects for testing&lt;/li&gt;
&lt;li&gt;✨ feat: testutil - adds a new function NewEchoServer() to start the echo server&lt;/li&gt;
&lt;li&gt;✨ feat: byteutil - Buffer adds more useful methods for ease of use&lt;/li&gt;
&lt;li&gt;✨ feat: dump - Special handling of custom int, uint type values, will print instructions in String format&lt;/li&gt;
&lt;li&gt;✨ feat: fsutil - adds a new function to Glob() quickly list matching files&lt;/li&gt;
&lt;li&gt;♻️ feat: httpreq - Refactoring the built-in HTTP client httpreq logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  👔 Update Adjustments
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;👔 up: structs - Update and support InitDefaults() for struct slice fields that are not null&lt;/li&gt;
&lt;li&gt;👔 up: maputil - &lt;code&gt;SimpleMerge()&lt;/code&gt; Supports deep merging of map[string]any data&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other adjustments
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ test: Update some documentation and fix some unit tests&lt;/li&gt;
&lt;li&gt;⬆️ dep: Update golang.org/x depends on the latest version&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Some feature usage examples
&lt;/h3&gt;

&lt;h4&gt;
  
  
  dump - prints custom types
&lt;/h4&gt;

&lt;p&gt;dump - special handles custom int, uint type values, and will print instructions in String format&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fEQkMjPf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/gookit/goutil/v0.6.10/dump/_examples/custom_type.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fEQkMjPf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/gookit/goutil/v0.6.10/dump/_examples/custom_type.png" alt="dump custom_type.png" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Initialize the struct
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Support for initializing the use of environment variables&lt;/li&gt;
&lt;li&gt;Support initializing slice fields and nesting structs
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ExtraDefault&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;City&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`default:"some where"`&lt;/span&gt;
    &lt;span class="n"&gt;Github&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`default:"${ GITHUB_ADDR }"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;        &lt;span class="s"&gt;`default:"inhere"`&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;   &lt;span class="kt"&gt;int&lt;/span&gt;           &lt;span class="s"&gt;`default:"300"`&lt;/span&gt;
    &lt;span class="n"&gt;Extra&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ExtraDefault&lt;/span&gt; &lt;span class="s"&gt;`default:""`&lt;/span&gt; &lt;span class="c"&gt;// mark: need init&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;optFn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;structs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InitOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseEnv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;structs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InitDefaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optFn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;goutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PanicErr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;dump&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Initialization result:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;structs_test&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"inhere"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;
  &lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;300&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;Extra&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;structs_test&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExtraDefault&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;City&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"some where"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;
    &lt;span class="n"&gt;Github&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://some .... url"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Test with Echo Server
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;testutil.NewEchoServer()&lt;/code&gt; to quickly create an HTTP echo server. Convenient for testing HTTP requests, responses, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Usage examples:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;testSrvAddr&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestMain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;testutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEchoServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;testSrvAddr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Addr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"server addr:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testSrvAddr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestNewEchoServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// can direct request the echo server&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testSrvAddr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text/plain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello!"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NoErr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// binding response to the testutil.EchoReply&lt;/span&gt;
    &lt;span class="n"&gt;rr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;testutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseRespToReply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;dump&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text/plain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hello!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  v0.6.9 change log
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Full changelog &lt;a href="https://github.com/gookit/goutil/compare/v0.6.8...v0.6.9"&gt;v0.6.8...v0.6.9&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  ✨ New features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;strutil - Added &lt;code&gt;ToByteSize(),SafeByteSize()&lt;/code&gt; for converting size string (eg: 5MB) to byte size&lt;/li&gt;
&lt;li&gt;strutil has added &lt;code&gt;ParseSizeRange()&lt;/code&gt; to facilitate and quickly parse string size range expressions eg: &lt;code&gt;200kb~50mb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;strutil - Added new utility functions: &lt;code&gt;DatetimeNo(), RandWithTpl(), SimpleMatch()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;byteutil - Add new utility functions: &lt;code&gt;Random()&lt;/code&gt;, &lt;code&gt;AppendAny()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;fsutil - Add new utility functions: &lt;code&gt;ReadOrErr()&lt;/code&gt;, &lt;code&gt;ReadStringOrErr()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;cliutil - Add new utility functions: &lt;code&gt;Confirm()&lt;/code&gt;, &lt;code&gt;ReadAsBool()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;errorx - Add new utility functions &lt;code&gt;Err(), Errf()&lt;/code&gt; for easy creation of error&lt;/li&gt;
&lt;li&gt;structs - &lt;code&gt;InitDefaults()&lt;/code&gt; enhanced to support nested structure pointer initialization&lt;/li&gt;
&lt;li&gt;structs - &lt;code&gt;SetValues()&lt;/code&gt; enhanced to support setting and processing structure pointer values&lt;/li&gt;
&lt;li&gt;structs - Add &lt;code&gt;ToSMap(), TryToSMap(), TryToSMap()&lt;/code&gt; to convert structure to string map&lt;/li&gt;
&lt;li&gt;testutil/assert new assertion methods &lt;code&gt;NotContainsKey()&lt;/code&gt;, &lt;code&gt;NotContainsKeys()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Reflects new utility methods &lt;code&gt;UnexportedValue()&lt;/code&gt;, &lt;code&gt;SetUnexportedValue()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;maputil new tool functions &lt;code&gt;HasOneKey(), CombineToMap(), TryAnyMap()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Added utility functions &lt;code&gt;AnyToSlice(), CombineToMap()&lt;/code&gt; in arrutil&lt;/li&gt;
&lt;li&gt;jsonutil has added tool methods &lt;code&gt;IsJSON(), IsJSONFast()&lt;/code&gt; to check whether it is JSON&lt;/li&gt;
&lt;li&gt;♻️ fsutil/finder file and directory search reconstruction, enhanced functions, more convenient to use&lt;/li&gt;
&lt;li&gt;timex new utility functions &lt;code&gt;NowAddSec(), IsDuration(), InRange()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;timex &lt;code&gt;ToDuration()&lt;/code&gt; enhanced, support unit d, w and long unit hour, min, sec&lt;/li&gt;
&lt;li&gt;mathutil new tool methods &lt;code&gt;InRange()&lt;/code&gt;, &lt;code&gt;OutRange()&lt;/code&gt;, &lt;code&gt;InUintRange()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;fsutil new tool method &lt;code&gt;RemoveSub()&lt;/code&gt; to quickly delete subdirectories and files&lt;/li&gt;
&lt;li&gt;maputil &lt;code&gt;GetByPath()&lt;/code&gt; is enhanced to support matching paths similar to &lt;code&gt;top.*.field&lt;/code&gt; to get values&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  👔 Update adjustments
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;strutil optimization &lt;code&gt;ToByteSize()&lt;/code&gt; and &lt;code&gt;GlobMatch()&lt;/code&gt; logic&lt;/li&gt;
&lt;li&gt;struts - &lt;code&gt;InitDefaults()&lt;/code&gt; supports initializing non-zero ptr substructure fields&lt;/li&gt;
&lt;li&gt;💥 struts - &lt;code&gt;InitDefaults()&lt;/code&gt; To initialize a substructure, the field must be marked with &lt;code&gt;default:""&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other adjustments
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;📝 doc: README documentation updated, some subpackages added README&lt;/li&gt;
&lt;li&gt;✅ test: Added and fixed some unit tests&lt;/li&gt;
&lt;li&gt;⬆️ dep: update golang.org/x dependencies to latest version&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Some feature usage examples
&lt;/h3&gt;

&lt;h4&gt;
  
  
  finder - find files or dir
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;fsutil/finder&lt;/code&gt; Provides a simple and fast way to find matching files and directories.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built-in support Name, extension, suffix, prefix, glob, path, etc. include or exclude&lt;/li&gt;
&lt;li&gt;Support matching file size, modification time (ModTime) and other extended matching methods
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;ff&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;finder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewFinder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/path/to/dir/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="c"&gt;// OnlyFindDir(). // default find files&lt;/span&gt;
    &lt;span class="n"&gt;UseAbsPath&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;WithoutDotDir&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;WithDirName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"testdata"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;Include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;finder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HumanModTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;10m"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="c"&gt;// latest 10 minutes, to Now&lt;/span&gt;
    &lt;span class="n"&gt;Include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;finder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HumanSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"500kb~10mb"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c"&gt;// limit file size&lt;/span&gt;

&lt;span class="c"&gt;// Find() returns chan, can be for handling&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Find&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;el&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  strutil.ParseSizeRange
&lt;/h4&gt;

&lt;p&gt;It is easy to parse the string size range to byte size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;opt&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;strutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseSizeOpt&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="n"&gt;mix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseSizeRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1kb~1mb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;goutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PanicErr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// OUTPUT: 1024, 1048576&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Examples of supported expression formats:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"1KB~2MB"       =&amp;gt; 1KB to 2MB
"-1KB"          =&amp;gt; &amp;lt;1KB
"~1MB"          =&amp;gt; &amp;lt;1MB
"&amp;lt; 1KB"         =&amp;gt; &amp;lt;1KB
"1KB"           =&amp;gt; &amp;gt;1KB
"1KB~"          =&amp;gt; &amp;gt;1KB
"&amp;gt;1KB"          =&amp;gt; &amp;gt;1KB
"+1KB"          =&amp;gt; &amp;gt;1KB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  timex.ParseRange()
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;timex.ParseRange()&lt;/code&gt; It is easy to quickly parse the relative time size range or keyword into &lt;code&gt;time.Time&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ParseRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-1h~1h"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;goutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PanicErr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Examples of supported expression formats:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"-5h~-1h"           =&amp;gt; 5 hours ago to 1 hour ago
"1h~5h"             =&amp;gt; 1 hour after to 5 hours after
"-1h~1h"            =&amp;gt; 1 hour ago to 1 hour after
"-1h"               =&amp;gt; 1 hour ago to feature. eq "-1h~"
"-1h~0"             =&amp;gt; 1 hour ago to now.
"&amp;lt; -1h" OR "~-1h"   =&amp;gt; 1 hour ago.
"&amp;gt; 1h" OR "1h"      =&amp;gt; 1 hour after to feature

// keyword: now, today, yesterday, tomorrow
"today"          =&amp;gt; today start to today end
"yesterday"      =&amp;gt; yesterday start to yesterday end
"tomorrow"       =&amp;gt; tomorrow start to tomorrow end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  More usage
&lt;/h2&gt;

&lt;p&gt;For more instructions, see Unit tests for &lt;a href="https://github.com/gookit/slog/blob/master/README.zh-CN.md"&gt;README&lt;/a&gt; and related methods&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Github&lt;/strong&gt;: &lt;a href="https://github.com/gookit/goutil"&gt;https://github.com/gookit/goutil&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>programming</category>
      <category>opensource</category>
      <category>go</category>
      <category>util</category>
    </item>
    <item>
      <title>gookit/slog - release v0.5.2, Lightweight, configurable, extensible logging library</title>
      <dc:creator>Inhere</dc:creator>
      <pubDate>Tue, 20 Jun 2023 08:10:20 +0000</pubDate>
      <link>https://forem.com/inhere/gookitslog-release-v052-lightweight-configurable-extensible-logging-library-5d9k</link>
      <guid>https://forem.com/inhere/gookitslog-release-v052-lightweight-configurable-extensible-logging-library-5d9k</guid>
      <description>&lt;p&gt;&lt;code&gt;gookit/slog&lt;/code&gt; 📑 Lightweight, configurable, extensible logging library written in Go.&lt;br&gt;
Support multi level, multi outputs and built-in multi file logger, buffers, clean, rotate-file handling.&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;Github &lt;a href="https://github.com/gookit/slog"&gt;https://github.com/gookit/slog&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  v0.5.2 changelog
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Full changelog&lt;/strong&gt;: &lt;a href="https://github.com/gookit/slog/compare/v0.5.1...v0.5.2"&gt;https://github.com/gookit/slog/compare/v0.5.1...v0.5.2&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Feature
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✨ feat: Add new option FilePerm to customize the permission on log file creation. issues #102 &lt;a href="https://github.com/gookit/slog/commit/699ecd8bc2dea0fb35607ba89d4299e86f96e40b"&gt;https://github.com/gookit/slog/commit/699ecd8bc2dea0fb35607ba89d4299e86f96e40b&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: rotatefile - Added new option &lt;code&gt;ModeCreate&lt;/code&gt; to support creating log files at rotation time. &lt;a href="https://github.com/gookit/slog/commit/8c4a9a08a9b3432a699f6770b73935ecfd42e5b8"&gt;https://github.com/gookit/slog/commit/8c4a9a08a9b3432a699f6770b73935ecfd42e5b8&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Update
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;👔 up: Update and add more unit tests, upgrade goutil to v0.6.10 &lt;a href="https://github.com/gookit/slog/commit/693cc04eb0e375183357be18893cbecaa171ffa1"&gt;https://github.com/gookit/slog/commit/693cc04eb0e375183357be18893cbecaa171ffa1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📝 doc: Update README document description &lt;a href="https://github.com/gookit/slog/commit/cbf77c38db5615a9a7ec8ab07853b2f9e3517bfa"&gt;https://github.com/gookit/slog/commit/cbf77c38db5615a9a7ec8ab07853b2f9e3517bfa&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✅ test: Add more unit test cases &lt;a href="https://github.com/gookit/slog/commit/8468ea470645bb981fb34002176671bac1a9559e"&gt;https://github.com/gookit/slog/commit/8468ea470645bb981fb34002176671bac1a9559e&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  New feature usage
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Custom log file permissions
&lt;/h3&gt;

&lt;p&gt;The log file permission flag created by configuring the &lt;code&gt;FilePerm&lt;/code&gt; setting of &lt;code&gt;hander.Config&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustFileHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tmp/error.log"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithLogLevels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DangerLevels&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithFilePerm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0644&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c"&gt;// &amp;lt;- sets log file permissions&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PushHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Split files using ModeCreate mode
&lt;/h3&gt;

&lt;p&gt;about &lt;code&gt;RotateMode&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ModeRename By default, every time rename handles rotation.&lt;/li&gt;
&lt;li&gt;ModeCreate Create files only by split time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Setting &lt;code&gt;RotateMode=ModeCreate&lt;/code&gt; allows log files to be created only by split time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustRotateFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"/tmp/error.log"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;rotatefile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EveryHour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// split by hour&lt;/span&gt;
    &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithLogLevels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DangerLevels&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithRotateMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rotatefile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModeCreate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c"&gt;// set RotateMode=ModeCreate&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PushHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure the logfile as &lt;code&gt;/tmp/error.log&lt;/code&gt; in the above example. When set to &lt;code&gt;ModeCreate&lt;/code&gt; mode, the file will not actually be created,&lt;br&gt;
Instead, it will be created according to the actual split time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/tmp/error.log.20230618_1500
/tmp/error.log.20230618_1600
/tmp/error.log.20230618_1700
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tips&lt;/strong&gt;: The &lt;code&gt;ModeCreate&lt;/code&gt; mode can be applied to command-line tool applications. Because they exit after each execution, &lt;code&gt;ModeRename&lt;/code&gt; may not be able to split files on time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And using &lt;code&gt;ModeRename&lt;/code&gt; mode will have the following effect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/tmp/error.log &lt;span class="c"&gt;# &amp;lt;- Logs are always written to this file&lt;/span&gt;
/tmp/error.log.20230618_1500
/tmp/error.log.20230618_1600
/tmp/error.log.20230618_1700
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  More usage
&lt;/h2&gt;

&lt;p&gt;More usage please see &lt;a href="https://github.com/gookit/slog/blob/master/README.md"&gt;README&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>github</category>
      <category>tooling</category>
    </item>
    <item>
      <title>GO tool library goutil released v0.6.4</title>
      <dc:creator>Inhere</dc:creator>
      <pubDate>Sun, 12 Feb 2023 03:52:39 +0000</pubDate>
      <link>https://forem.com/inhere/go-tool-library-goutil-released-v064-56nj</link>
      <guid>https://forem.com/inhere/go-tool-library-goutil-released-v064-56nj</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/gookit/goutil" rel="noopener noreferrer"&gt;gookit/goutil&lt;/a&gt; - 💪 Helper Utils For Go: int, byte, string, array/slice, map, struct, dump, convert/format, error, web/http, cli/flag, OS/ENV, filesystem, system, test/assert, time and more. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;GitHub: &lt;a href="https://github.com/gookit/goutil" rel="noopener noreferrer"&gt;https://github.com/gookit/goutil&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Changlog from v0.6.2 to v0.6.4
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Fixed
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🐛 fix(env, str): fix the envutil test error and update some str util &lt;a href="https://github.com/gookit/goutil/commit/2e7aa6329973423a76ea6b9b20a8b9150281dfb1" rel="noopener noreferrer"&gt;2e7aa63&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐛 fix(dump): makeslice: cap out of range. fix: #76 &lt;a href="https://github.com/gookit/goutil/commit/4ba9b10e15a448eee1b8d2974835fc69407618ff" rel="noopener noreferrer"&gt;4ba9b10&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Feature
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;👔 feat: str - add some check util func &lt;a href="https://github.com/gookit/goutil/commit/0e4792acf21e1bf742f1af5882b74ff40c49b935" rel="noopener noreferrer"&gt;0e4792a&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 feat: str/textutil - support quick replace vars for give text &lt;a href="https://github.com/gookit/goutil/commit/ecc23cb0cec4c518623b08c37f2e1fd948d6bea2" rel="noopener noreferrer"&gt;ecc23cb&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 feat: sys,proc - add and update some util func &lt;a href="https://github.com/gookit/goutil/commit/aa78114b0da1017f6456957ba86cd24eeebe5fc7" rel="noopener noreferrer"&gt;aa78114&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: fs - add more new fs util functions &lt;a href="https://github.com/gookit/goutil/commit/3352512f6a133ae15a57944bc54362b604c7ff95" rel="noopener noreferrer"&gt;3352512&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: map, struct - add new util functions &lt;a href="https://github.com/gookit/goutil/commit/90af09e118b4a521c19341e6b8a49a0890e22e7f" rel="noopener noreferrer"&gt;90af09e&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: stdio - add new util functions &lt;a href="https://github.com/gookit/goutil/commit/ea243d62c89dc9ec7be9fd6a9b0bcdb39bfd506b" rel="noopener noreferrer"&gt;ea243d6&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: arr - add new util functions for in/notIn check &lt;a href="https://github.com/gookit/goutil/commit/2a18ca2915c93e53aea74e86779943f04bd1910a" rel="noopener noreferrer"&gt;2a18ca2&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: testutil - add new util func IsMatchAll() &lt;a href="https://github.com/gookit/goutil/commit/d0dade8703da172f80424ff8c85ec759ec8273ae" rel="noopener noreferrer"&gt;d0dade8&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: math - add new util func for compare value &lt;a href="https://github.com/gookit/goutil/commit/176923bb953622b995ed80017056cbe04db251cd" rel="noopener noreferrer"&gt;176923b&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;feat: error, test - add some new helper util fuctions &lt;a href="https://github.com/gookit/goutil/commit/718821631d8a7cc0567a2f39eece80f1b7c54157" rel="noopener noreferrer"&gt;7188216&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: fs - add more make dir util func &lt;a href="https://github.com/gookit/goutil/commit/c4447cb0d32cec53221c3bb99a14ecefc4ec382e" rel="noopener noreferrer"&gt;c4447cb&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: env,sys - add new func for get all env info map &lt;a href="https://github.com/gookit/goutil/commit/b3d7669d1a1c851d7f75e2a9ad449d74ca6c969c" rel="noopener noreferrer"&gt;b3d7669&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: str - add new func for check ignore case string &lt;a href="https://github.com/gookit/goutil/commit/746eb35d45a9c0d40fb9ae7945c9fe89bbc79765" rel="noopener noreferrer"&gt;746eb35&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: goutil - add new func for quick run go func &lt;a href="https://github.com/gookit/goutil/commit/97a2863089d70a2d39f5fa720f74890767293d0b" rel="noopener noreferrer"&gt;97a2863&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: arr - add new func for quick convert slice type &lt;a href="https://github.com/gookit/goutil/commit/75d8d89f4cb7e9c59587caeccfeb73202beb42b1" rel="noopener noreferrer"&gt;75d8d89&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: reflects - add new func for convert slice value and more util &lt;a href="https://github.com/gookit/goutil/commit/f87fc86119afd8418b47e93ad26b3925f78bef15" rel="noopener noreferrer"&gt;f87fc86&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: structs - func InitDefaults() support set slice field &lt;a href="https://github.com/gookit/goutil/commit/948fa703e7107edb4dc736aa041c260fc8df7d9b" rel="noopener noreferrer"&gt;948fa70&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: byte - add StrOrErr(), SafeString() for convert to string &lt;a href="https://github.com/gookit/goutil/commit/767ed80a5e98d20b9e832a08d065de301ba0b4ec" rel="noopener noreferrer"&gt;767ed80&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ feat: cmdr - add new option for output result to OS &lt;a href="https://github.com/gookit/goutil/commit/6aaea78dee886b7aa5483d71826a34813d8cd77b" rel="noopener noreferrer"&gt;6aaea78&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Update
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;👔 up: str, math - add new util func OrElse() &lt;a href="https://github.com/gookit/goutil/commit/cb21fbc4624c800f9609137e053dfe2fef027190" rel="noopener noreferrer"&gt;cb21fbc&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 up: str - update some util func and add more tests &lt;a href="https://github.com/gookit/goutil/commit/a3e07f4b5fbbb6131d42116a4e1c61c7614d7d69" rel="noopener noreferrer"&gt;a3e07f4&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐛 up: textscan - fix multi inline comments parse error &lt;a href="https://github.com/gookit/goutil/commit/bf68c945ee79d7e214087ab117b55fa02b0f1c54" rel="noopener noreferrer"&gt;bf68c94&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 up: str,math - update some util func &lt;a href="https://github.com/gookit/goutil/commit/eaf09908ead83f19d6a10882547e5cda1e42a79e" rel="noopener noreferrer"&gt;eaf0990&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 up: str,byte - add and update some util func &lt;a href="https://github.com/gookit/goutil/commit/cf5d34e6b20bf45830fed19a3d3b6ac4682cdade" rel="noopener noreferrer"&gt;cf5d34e&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 up: byte,cflag - update and add some new tests &lt;a href="https://github.com/gookit/goutil/commit/6e47f6911ed99225a1b5f6fdf6cfafe3b034e333" rel="noopener noreferrer"&gt;6e47f69&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 up(env, str): update the env var parse and strutil.Valid() &lt;a href="https://github.com/gookit/goutil/commit/5193849498317900885f524fae7cf5777559f246" rel="noopener noreferrer"&gt;5193849&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 up(str): update some str value get func &lt;a href="https://github.com/gookit/goutil/commit/676fe4e08e7313c593278d9e4f734225381e6be3" rel="noopener noreferrer"&gt;676fe4e&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ up(env,sys): update some func and add new util func &lt;a href="https://github.com/gookit/goutil/commit/9eaddb5669280dc91c989e4930ecd1efbdef18cf" rel="noopener noreferrer"&gt;9eaddb5&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 up(str): update the SplitInlineComment() logic &lt;a href="https://github.com/gookit/goutil/commit/31445cd999e5577b9e7e7f6d3e9efe3289fd7131" rel="noopener noreferrer"&gt;31445cd&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 up(sys): update the SearchPath(), support limit result &lt;a href="https://github.com/gookit/goutil/commit/67cbae1d5db5c5ec09240917fae73c78e7d9e9d6" rel="noopener noreferrer"&gt;67cbae1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✅ up(sys,env,map): add more tests case for util func &lt;a href="https://github.com/gookit/goutil/commit/392536c6b91555d25cb5cbca8dc6ab81a56b92b9" rel="noopener noreferrer"&gt;392536c&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 up(fs,sys): update some fs and sys util func run logic &lt;a href="https://github.com/gookit/goutil/commit/772762873ad9fa766afce0841d0343078770545e" rel="noopener noreferrer"&gt;7727628&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 up(struct): update some structs comments and update readme &lt;a href="https://github.com/gookit/goutil/commit/f461852b5dff186ce1467af42ec31a89f3ae3c22" rel="noopener noreferrer"&gt;f461852&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👔 up(str): update some string util comments and func &lt;a href="https://github.com/gookit/goutil/commit/796d1fe6674337176b82ef71bd1e47b26b80b072" rel="noopener noreferrer"&gt;796d1fe&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;build(deps): bump golang.org/x/text from 0.5.0 to 0.6.0 &lt;a href="https://github.com/gookit/goutil/commit/79d77815079d167871c65f27186911014fdb53fd" rel="noopener noreferrer"&gt;79d7781&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;doc: re-generate the README docs &lt;a href="https://github.com/gookit/goutil/commit/42e30848e174ad8b442132b89d0c910b4c8be673" rel="noopener noreferrer"&gt;42e3084&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;doc: update the doc parse logic, support generic types &lt;a href="https://github.com/gookit/goutil/commit/030676da0275c93e1e67af344c0fd88cccad3b3e" rel="noopener noreferrer"&gt;030676d&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;doc: generate and update README docs &lt;a href="https://github.com/gookit/goutil/commit/f342e92004e670fc2aee7f72d0caa21f4172a347" rel="noopener noreferrer"&gt;f342e92&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;build(deps): bump golang.org/x/text from 0.6.0 to 0.7.0 &lt;a href="https://github.com/gookit/goutil/commit/1e3ea77d248bcecbeb26fcf8d3ef520d2bdd8829" rel="noopener noreferrer"&gt;1e3ea77&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;GitHub: &lt;a href="https://github.com/gookit/goutil" rel="noopener noreferrer"&gt;https://github.com/gookit/goutil&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Lightweight event management, dispatch tool library implemented by Go</title>
      <dc:creator>Inhere</dc:creator>
      <pubDate>Thu, 07 Jul 2022 14:37:14 +0000</pubDate>
      <link>https://forem.com/inhere/lightweight-event-management-dispatch-tool-library-implemented-by-go-583p</link>
      <guid>https://forem.com/inhere/lightweight-event-management-dispatch-tool-library-implemented-by-go-583p</guid>
      <description>&lt;p&gt;&lt;code&gt;event&lt;/code&gt; - Lightweight event management, dispatch tool library implemented by Go&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support for custom definition event objects&lt;/li&gt;
&lt;li&gt;Support for adding multiple listeners to an event&lt;/li&gt;
&lt;li&gt;Supports setting the priority of the event listener. The higher the priority, the higher the trigger.&lt;/li&gt;
&lt;li&gt;Support for a set of event listeners based on the event name prefix &lt;code&gt;PREFIX.*&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;add &lt;code&gt;app.*&lt;/code&gt; event listen, trigger &lt;code&gt;app.run&lt;/code&gt; &lt;code&gt;app.end&lt;/code&gt;, Both will trigger the &lt;code&gt;app.*&lt;/code&gt; event at the same time&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Support for using the wildcard &lt;code&gt;*&lt;/code&gt; to listen for triggers for all events&lt;/li&gt;
&lt;li&gt;Complete unit testing, unit coverage &lt;code&gt;&amp;gt; 95%&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Repo and doc
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Github: &lt;a href="https://github.com/gookit/event"&gt;https://github.com/gookit/event&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pkg.go.dev/github.com/gookit/event"&gt;Godoc for github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/gookit/event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/gookit/event"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Register event listener&lt;/span&gt;
    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;On&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"evt1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenerFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"handle event: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Normal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Register multiple listeners&lt;/span&gt;
    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;On&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"evt1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenerFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"handle event: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;High&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// ... ...&lt;/span&gt;

    &lt;span class="c"&gt;// Trigger event&lt;/span&gt;
    &lt;span class="c"&gt;// Note: The second listener has a higher priority, so it will be executed first.&lt;/span&gt;
    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustFire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"evt1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"arg0"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"val0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"arg1"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"val1"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: The second listener has a higher priority, so it will be executed first.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Using the wildcard
&lt;/h3&gt;

&lt;p&gt;Register event listener and name end with wildcard &lt;code&gt;*&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;dbListener1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenerFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"handle event: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;On&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"app.db.*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dbListener1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Normal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trigger events on other logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;doCreate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// do something ...&lt;/span&gt;
    &lt;span class="c"&gt;// Trigger event&lt;/span&gt;
    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustFire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"app.db.create"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"arg0"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"val0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"arg1"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"val1"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;doUpdate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// do something ...&lt;/span&gt;
    &lt;span class="c"&gt;// Trigger event&lt;/span&gt;
    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustFire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"app.db.update"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"arg0"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"val0"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like the above, triggering the &lt;code&gt;app.db.create&lt;/code&gt; &lt;code&gt;app.db.update&lt;/code&gt; event&lt;br&gt;
will trigger the execution of the &lt;code&gt;dbListener1&lt;/code&gt; listener.&lt;/p&gt;
&lt;h2&gt;
  
  
  Write event listeners
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Using anonymous functions
&lt;/h3&gt;

&lt;p&gt;You can use anonymous function for quick write an event lister.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;mypgk&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/gookit/event"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fnHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"handle event: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// register&lt;/span&gt;
    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;On&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"evt1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenerFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fnHandler&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;High&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using the structure method
&lt;/h3&gt;

&lt;p&gt;You can use struct write an event lister, and it should implementation interface &lt;code&gt;event.Listener&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;interface:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Listener interface&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Listener&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;example:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Implementation interface &lt;code&gt;event.Listener&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;mypgk&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/gookit/event"&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;MyListener&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// userData string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MyListener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Register multiple event listeners
&lt;/h2&gt;

&lt;p&gt;Can implementation interface &lt;code&gt;event.Subscriber&lt;/code&gt; for register&lt;br&gt;
multiple event listeners at once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;interface:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Subscriber event subscriber interface.&lt;/span&gt;
&lt;span class="c"&gt;// you can register multi event listeners in a struct func.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Subscriber&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// SubscribedEvents register event listeners&lt;/span&gt;
    &lt;span class="c"&gt;// key: is event name&lt;/span&gt;
    &lt;span class="c"&gt;// value: can be Listener or ListenerItem interface&lt;/span&gt;
    &lt;span class="n"&gt;SubscribedEvents&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;example&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Implementation interface &lt;code&gt;event.Subscriber&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;mypgk&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/gookit/event"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;MySubscriber&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// ooo&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MySubscriber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SubscribedEvents&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
        &lt;span class="s"&gt;"e1"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenerFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;e1Handler&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s"&gt;"e2"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenerItem&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Priority&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AboveNormal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Listener&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenerFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"an error"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s"&gt;"e3"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;MyListener&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MySubscriber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;e1Handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"e1-key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"val1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Write custom events
&lt;/h2&gt;

&lt;p&gt;If you want to customize the event object or define some fixed event information in advance,&lt;br&gt;
you can implement the &lt;code&gt;event.Event&lt;/code&gt; interface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;interface:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Event interface&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Event&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="c"&gt;// Target() interface{}&lt;/span&gt;
    &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;SetData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Event&lt;/span&gt;
    &lt;span class="n"&gt;Abort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;IsAborted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;examples:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;mypgk&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/gookit/event"&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;MyEvent&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BasicEvent&lt;/span&gt;
    &lt;span class="n"&gt;customData&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MyEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;CustomData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customData&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;MyEvent&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;customData&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"e1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// add listener&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;On&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"e1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenerFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"custom Data: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MyEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomData&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}))&lt;/span&gt;

&lt;span class="c"&gt;// trigger&lt;/span&gt;
&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"e1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// OR&lt;/span&gt;
&lt;span class="c"&gt;// event.FireEvent(e)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Main method
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;On/Listen(name string, listener Listener, priority ...int)&lt;/code&gt; Register event listener&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Subscribe/AddSubscriber(sbr Subscriber)&lt;/code&gt;  Subscribe to support registration of multiple event listeners&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Trigger/Fire(name string, params M) (error, Event)&lt;/code&gt; Trigger event by name and params&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MustTrigger/MustFire(name string, params M) Event&lt;/code&gt;   Trigger event, there will be panic if there is an error&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FireEvent(e Event) (err error)&lt;/code&gt;    Trigger an event based on a given event instance&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FireBatch(es ...interface{}) (ers []error)&lt;/code&gt; Trigger multiple events at once&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AsyncFire(e Event)&lt;/code&gt;   Async fire event by 'go' keywords&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>opensource</category>
      <category>github</category>
      <category>go</category>
    </item>
    <item>
      <title>slog - Lightweight, configurable, extensible Go logging library</title>
      <dc:creator>Inhere</dc:creator>
      <pubDate>Thu, 16 Jun 2022 02:33:47 +0000</pubDate>
      <link>https://forem.com/inhere/slog-lightweight-configurable-extensible-go-logging-library-52h2</link>
      <guid>https://forem.com/inhere/slog-lightweight-configurable-extensible-go-logging-library-52h2</guid>
      <description>&lt;p&gt;&lt;code&gt;slog&lt;/code&gt; is a lightweight, configurable, extensible Go logging library.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgookit%2Fslog%2Fmaster%2F_example%2Fimages%2Fconsole-log-all-level.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgookit%2Fslog%2Fmaster%2F_example%2Fimages%2Fconsole-log-all-level.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Simple, directly available without configuration&lt;/li&gt;
&lt;li&gt;Support common log level processing.

&lt;ul&gt;
&lt;li&gt;eg: &lt;code&gt;trace&lt;/code&gt; &lt;code&gt;debug&lt;/code&gt; &lt;code&gt;info&lt;/code&gt; &lt;code&gt;notice&lt;/code&gt; &lt;code&gt;warn&lt;/code&gt; &lt;code&gt;error&lt;/code&gt; &lt;code&gt;fatal&lt;/code&gt; &lt;code&gt;panic&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Support any extension of &lt;code&gt;Handler&lt;/code&gt; &lt;code&gt;Formatter&lt;/code&gt; as needed&lt;/li&gt;

&lt;li&gt;Supports adding multiple &lt;code&gt;Handler&lt;/code&gt; log processing at the same time, outputting logs to different places&lt;/li&gt;

&lt;li&gt;Support to custom log message &lt;code&gt;Formatter&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Built-in &lt;code&gt;json&lt;/code&gt; &lt;code&gt;text&lt;/code&gt; two log record formatting &lt;code&gt;Formatter&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Support to custom build log messages &lt;code&gt;Handler&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;The built-in &lt;code&gt;handler.Config&lt;/code&gt; &lt;code&gt;handler.Builder&lt;/code&gt; can easily and quickly build the desired log handler&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Has built-in common log write handler program

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;console&lt;/code&gt; output logs to the console, supports color output&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;writer&lt;/code&gt; output logs to the specified &lt;code&gt;io.Writer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;file&lt;/code&gt; output log to the specified file, optionally enable &lt;code&gt;buffer&lt;/code&gt; to buffer writes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;simple&lt;/code&gt; output log to the specified file, write directly to the file without buffering&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rotate_file&lt;/code&gt; outputs logs to the specified file, and supports splitting files by time and size, and &lt;code&gt;buffer&lt;/code&gt; buffered writing is enabled by default&lt;/li&gt;
&lt;li&gt;See ./handler folder for more built-in implementations&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Output logs to file
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Support enabling &lt;code&gt;buffer&lt;/code&gt; for log writing&lt;/li&gt;
&lt;li&gt;Support splitting log files by &lt;code&gt;time&lt;/code&gt; and &lt;code&gt;size&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Support configuration to compress log files via &lt;code&gt;gzip&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Support clean old log files by &lt;code&gt;BackupNum&lt;/code&gt; &lt;code&gt;BackupTime&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Git repository
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Github: &lt;a href="https://github.com/gookit/slog" rel="noopener noreferrer"&gt;https://github.com/gookit/slog&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/gookit/slog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gookit/slog"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"this is a log message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"this is a log message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"this is a log message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Notice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"this is a log message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"this is a log message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"this is a log message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"this is a log message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;output preview:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgookit%2Fslog%2Fmaster%2F_example%2Fimages%2Fconsole-log-all-level.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgookit%2Fslog%2Fmaster%2F_example%2Fimages%2Fconsole-log-all-level.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Logs to file
&lt;/h2&gt;

&lt;p&gt;Using &lt;code&gt;slog&lt;/code&gt; to output logs to files is very convenient, and supports multiple files, splitting by time, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gookit/slog"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gookit/slog/handler"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gookit/slog/rotatefile"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustFlush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// DangerLevels contains: slog.PanicLevel, slog.ErrorLevel, slog.WarnLevel&lt;/span&gt;
    &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustRotateFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tmp/logs/app_error.log"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rotatefile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EveryHour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithLogLevels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DangerLevels&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// NormalLevels contains: slog.InfoLevel, slog.NoticeLevel, slog.DebugLevel, slog.TraceLevel&lt;/span&gt;
    &lt;span class="n"&gt;h2&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustRotateFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tmp/logs/app_info.log"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rotatefile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EveryHour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithLogLevels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NormalLevels&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PushHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PushHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// add logs&lt;/span&gt;
    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"info message text"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error message text"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See logs dir:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /tmp/logs
app_error.log
app_info.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  More usage
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;More usage please see &lt;a href="https://github.com/gookit/slog/blob/master/README.zh-CN.md" rel="noopener noreferrer"&gt;README&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>log</category>
      <category>opensource</category>
    </item>
    <item>
      <title>gookit/goutil - Useful utils package for the Go</title>
      <dc:creator>Inhere</dc:creator>
      <pubDate>Mon, 13 Jun 2022 07:40:15 +0000</pubDate>
      <link>https://forem.com/inhere/gookitgoutil-useful-utils-package-for-the-go-15bh</link>
      <guid>https://forem.com/inhere/gookitgoutil-useful-utils-package-for-the-go-15bh</guid>
      <description>&lt;p&gt;&lt;code&gt;gookit/goutil&lt;/code&gt; 💪 Useful utils package for the Go: int, string, array/slice, map, error, time, format, CLI, ENV, filesystem, system, testing and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sub-packages
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;arrutil&lt;/code&gt;: Array/Slice util functions. eg: check, convert, formatting&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dump&lt;/code&gt;: Simple variable printing tool, printing slice, map will automatically wrap each element and display the call location&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cliutil&lt;/code&gt; Command-line util functions. eg: read input, exec command, cmdline parse/build&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;errorx&lt;/code&gt; Provide an enhanced error implements for go, allow with stacktraces and wrap another error.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;envutil&lt;/code&gt; ENV util for current runtime env information. eg: get one, get info, parse var&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fmtutil&lt;/code&gt; Format data util functions. eg: data, size&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fsutil&lt;/code&gt; Filesystem util functions, quick create, read and write file. eg: file and dir check, operate&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jsonutil&lt;/code&gt; some util functions for quick read, write, encode, decode JSON data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;maputil&lt;/code&gt; Map data util functions. eg: convert, sub-value get, simple merge&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mathutil&lt;/code&gt;Math(int, number) util functions. eg: convert, math calc, random&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;netutil&lt;/code&gt; Network util functions

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;netutil/httpreq&lt;/code&gt; An easier-to-use HTTP client that wraps http.Client&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;strutil&lt;/code&gt; String util functions. eg: bytes, check, convert, encode, format and more&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;sysutil&lt;/code&gt; System util functions. eg: sysenv, exec, user, process&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;testutil&lt;/code&gt; Test help util functions. eg: http test, mock ENV value&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;timex&lt;/code&gt; Provides an enhanced time.Time implementation. Add more commonly used functional methods

&lt;ul&gt;
&lt;li&gt;such as: DayStart(), DayAfter(), DayAgo(), DateFormat() and more.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Git repository
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Github: &lt;a href="https://github.com/gookit/goutil" rel="noopener noreferrer"&gt;https://github.com/gookit/goutil&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Gitee: &lt;a href="https://gitee.com/gookit/goutil" rel="noopener noreferrer"&gt;https://gitee.com/gookit/goutil&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/gookit/goutil
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  goutil/dump
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;goutil/dump&lt;/code&gt;  is a golang data printing toolkit that prints beautiful and easy to read go slice, map, struct data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;//  go run ./dump/_examples/struct.go&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cannotExport&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="n"&gt;cannotExport&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
            &lt;span class="s"&gt;"key1"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"key2"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"abcd123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;s2&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ab&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;Cd&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="s"&gt;"ab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infoln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"- Use fmt.Println:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infoln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;- Use dump.Println:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;dump&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgookit%2Fgoutil%2Fmaster%2Fdump%2F_examples%2Fstruct.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgookit%2Fgoutil%2Fmaster%2Fdump%2F_examples%2Fstruct.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  goutil/timex
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;goutil/timex&lt;/code&gt; Provides an enhanced time.Time implementation, and add more commonly used functional methods. &lt;/p&gt;

&lt;p&gt;such as: DayStart(), DayAfter(), DayAgo(), DateFormat() and more&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create timex instance:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;timex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c"&gt;// from time.Time&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;timex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;timex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="c"&gt;// from time unix&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;timex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromUnix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1647411580&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create time for date string&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// auto match layout by datetime&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;  &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;timex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2022-04-20 19:40:34"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// custom set the datetime layout&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;  &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;timex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2022-04-20 19:40:34"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"2006-01-02 15:04:05"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// use date template as layout&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;  &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;timex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2022-04-20 19:40:34"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Y-m-d H:I:S"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Quickly fetch time&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;timex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Yesterday&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tomorrow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DayStart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// get time at Y-m-d 00:00:00&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DayEnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// get time at Y-m-d 23:59:59&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HourStart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// get time at Y-m-d H:00:00&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HourEnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// get time at Y-m-d H:59:59&lt;/span&gt;

&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHour&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddMinutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;120&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Quickly format date&lt;/strong&gt;：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"y/m/d H:I"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Y-m-d H:I:S"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Output: 2022-04-20 19:40:34&lt;/span&gt;
&lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"y-m-d H:I:S"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Output: 22-04-20 19:40:34&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  More usage
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;More utils and usage please see README &lt;a href="https://github.com/gookit/goutil/blob/master/README.md" rel="noopener noreferrer"&gt;https://github.com/gookit/goutil/blob/master/README.md&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>github</category>
      <category>opensource</category>
    </item>
    <item>
      <title>goutil/dump - print beautiful and easy-to-read go data</title>
      <dc:creator>Inhere</dc:creator>
      <pubDate>Thu, 24 Feb 2022 05:03:29 +0000</pubDate>
      <link>https://forem.com/inhere/goutildump-print-beautiful-and-easy-to-read-go-data-504j</link>
      <guid>https://forem.com/inhere/goutildump-print-beautiful-and-easy-to-read-go-data-504j</guid>
      <description>&lt;p&gt;&lt;code&gt;goutil/dump&lt;/code&gt; - is a golang data printing toolkit that can print beautiful and easy-to-read go slice, map, and struct data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;main functions&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple to use, just call &lt;code&gt;dump.P(vars…)&lt;/code&gt; directly&lt;/li&gt;
&lt;li&gt;Supports all basic data types.&lt;/li&gt;
&lt;li&gt;Supports slice, map, and struct data structures.&lt;/li&gt;
&lt;li&gt;Supports passing in and printing multiple variables&lt;/li&gt;
&lt;li&gt;Default output call location, easy to use&lt;/li&gt;
&lt;li&gt;Supports custom features, such as indentation and color themes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Preview&lt;/strong&gt;：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffq9k1y8yulrokx2cd77u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffq9k1y8yulrokx2cd77u.png" alt="output-example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Git Repo:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Github: &lt;a href="https://github.com/gookit/goutil" rel="noopener noreferrer"&gt;https://github.com/gookit/goutil/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GoDoc: &lt;a href="https://pkg.go.dev/github.com/gookit/goutil/dump" rel="noopener noreferrer"&gt;https://pkg.go.dev/github.com/gookit/goutil/dump&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Print basic type
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/gookit/goutil/dump"&lt;/span&gt;

&lt;span class="c"&gt;// rum demo:&lt;/span&gt;
&lt;span class="c"&gt;//     go run ./dump/_examples/basic_types.go&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;dump&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kt"&gt;int16&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="kt"&gt;uint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kt"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kt"&gt;uint32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="kt"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;23.78&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;56.45&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sc"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwva7m0bigau7cc5wkcxy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwva7m0bigau7cc5wkcxy.png" alt="print-basic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Print slice
&lt;/h2&gt;

&lt;p&gt;Printing array, slice will output one element per line, and will output the length at the end.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/gookit/goutil/dump"&lt;/span&gt;

&lt;span class="c"&gt;// rum demo:&lt;/span&gt;
&lt;span class="c"&gt;//     go run ./dump/_examples/slice.go&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;dump&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"abc"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"ab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cd"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
            &lt;span class="s"&gt;"ab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="m"&gt;234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"ab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cd"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqk3jkepvfo16pvesi4u9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqk3jkepvfo16pvesi4u9.png" alt="print-slice"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Print map
&lt;/h2&gt;

&lt;p&gt;When printing the map data structure, one element per line is output, and the length of the map is output at the end.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/gookit/goutil/dump"&lt;/span&gt;

&lt;span class="c"&gt;// rum demo:&lt;/span&gt;
&lt;span class="c"&gt;//     go run ./map.go&lt;/span&gt;
&lt;span class="c"&gt;//     go run ./dump/_examples/map.go&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;dump&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
            &lt;span class="s"&gt;"key0"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"key1"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"value1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"key2"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="s"&gt;"key3"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;"k0"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"v0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"k1"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkzb4e6mjfjc1h3r4d92.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkzb4e6mjfjc1h3r4d92.png" alt="print-map"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Print struct
&lt;/h2&gt;

&lt;p&gt;Print struct data, the pointer type will automatically print the underlying real data.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gookit/color"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gookit/goutil/dump"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// rum demo:&lt;/span&gt;
&lt;span class="c"&gt;//     go run ./struct.go&lt;/span&gt;
&lt;span class="c"&gt;//     go run ./dump/_examples/struct.go&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cannotExport&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="n"&gt;cannotExport&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
            &lt;span class="s"&gt;"key1"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"key2"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"abcd123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;    &lt;span class="n"&gt;s2&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ab&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;Cd&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="s"&gt;"ab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infoln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"- Use fmt.Println:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infoln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;- Use dump.Println:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;dump&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9e1obvxn0h7bp34b3tsf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9e1obvxn0h7bp34b3tsf.png" alt="print-struct"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom dumper
&lt;/h2&gt;

&lt;p&gt;you can customize dumper options. Such as indentation and color theme&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="c"&gt;// Options for dump vars&lt;/span&gt;&lt;br&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Options&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
    &lt;span class="c"&gt;// Output the output writer&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;br&gt;
    &lt;span class="c"&gt;// NoType dont show data type TODO&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;NoType&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;br&gt;
    &lt;span class="c"&gt;// NoColor don't with color&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;NoColor&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;br&gt;
    &lt;span class="c"&gt;// IndentLen width. default is 2&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;IndentLen&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;br&gt;
    &lt;span class="c"&gt;// IndentChar default is one space&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;IndentChar&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;br&gt;
    &lt;span class="c"&gt;// MaxDepth for nested print&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;MaxDepth&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;br&gt;
    &lt;span class="c"&gt;// ShowFlag for display caller position&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;ShowFlag&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;br&gt;
    &lt;span class="c"&gt;// MoreLenNL array/slice elements length &amp;gt; MoreLenNL, will wrap new line&lt;/span&gt;&lt;br&gt;
    &lt;span class="c"&gt;// MoreLenNL int&lt;/span&gt;&lt;br&gt;
    &lt;span class="c"&gt;// CallerSkip skip for call runtime.Caller()&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;CallerSkip&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;br&gt;
    &lt;span class="c"&gt;// ColorTheme for print result.&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;ColorTheme&lt;/span&gt; &lt;span class="n"&gt;Theme&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Git &amp;amp; docs&lt;br&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Github: &lt;a href="https://github.com/gookit/goutil" rel="noopener noreferrer"&gt;https://github.com/gookit/goutil/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GoDoc: &lt;a href="https://pkg.go.dev/github.com/gookit/goutil/dump" rel="noopener noreferrer"&gt;https://pkg.go.dev/github.com/gookit/goutil/dump&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>tooling</category>
      <category>gookit</category>
      <category>commandline</category>
    </item>
  </channel>
</rss>
