file

package
v2.2.13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 10, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Example (Read_basicUsage)

Example_read_basicUsage demonstrates basic usage of the Read function to read data from a file with automatic resource cleanup.

package main

import (
	"fmt"
	"io"
	"os"

	FL "github.com/IBM/fp-go/v2/file"
	F "github.com/IBM/fp-go/v2/function"

	I "github.com/IBM/fp-go/v2/io"
	"github.com/IBM/fp-go/v2/ioresult"
	"github.com/IBM/fp-go/v2/ioresult/file"
)

func main() {
	// Create a temporary file for demonstration
	tmpFile, err := os.CreateTemp("", "example-*.txt")
	if err != nil {
		fmt.Printf("Error creating temp file: %v\n", err)
		return
	}
	defer os.Remove(tmpFile.Name())

	// Write some test data
	testData := "Hello, World! This is a test file."
	if _, err := tmpFile.WriteString(testData); err != nil {
		fmt.Printf("Error writing to temp file: %v\n", err)
		return
	}
	tmpFile.Close()

	// Define a reader function that reads the full file content
	readAll := F.Flow2(
		FL.ToReader[*os.File],
		ioresult.Eitherize1(io.ReadAll),
	)

	content := F.Pipe2(
		readAll,
		file.Read[[]byte](file.Open(tmpFile.Name())),
		ioresult.TapIOK(I.Printf[[]byte]("%s\n")),
	)

	content()

}
Output:
Hello, World! This is a test file.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// Open opens a file for reading
	Open = file.Open
	// Create opens a file for writing
	Create = file.Create
	// ReadFile reads the context of a file
	ReadFile = file.ReadFile
	// Stat returns [FileInfo] object
	Stat = file.Stat

	// UserCacheDir returns an [IOResult] that resolves to the default root directory
	// to use for user-specific cached data. Users should create their own application-specific
	// subdirectory within this one and use that.
	//
	// On Unix systems, it returns $XDG_CACHE_HOME as specified by
	// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html if
	// non-empty, else $HOME/.cache.
	// On Darwin, it returns $HOME/Library/Caches.
	// On Windows, it returns %LocalAppData%.
	// On Plan 9, it returns $home/lib/cache.
	//
	// If the location cannot be determined (for example, $HOME is not defined),
	// then it will return an error wrapped in [Err].
	UserCacheDir = file.UserCacheDir

	// UserConfigDir returns an [IOResult] that resolves to the default root directory
	// to use for user-specific configuration data. Users should create their own
	// application-specific subdirectory within this one and use that.
	//
	// On Unix systems, it returns $XDG_CONFIG_HOME as specified by
	// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html if
	// non-empty, else $HOME/.config.
	// On Darwin, it returns $HOME/Library/Application Support.
	// On Windows, it returns %AppData%.
	// On Plan 9, it returns $home/lib.
	//
	// If the location cannot be determined (for example, $HOME is not defined),
	// then it will return an error wrapped in [Err].
	UserConfigDir = file.UserConfigDir

	// UserHomeDir returns an [IOResult] that resolves to the current user's home directory.
	//
	// On Unix, including macOS, it returns the $HOME environment variable.
	// On Windows, it returns %USERPROFILE%.
	// On Plan 9, it returns the $home environment variable.
	//
	// If the location cannot be determined (for example, $HOME is not defined),
	// then it will return an error wrapped in [Err].
	UserHomeDir = file.UserHomeDir
)
View Source
var (
	// CreateTemp creates a temporary file with proper parametrization.
	// It is an alias for ioeither.file.CreateTemp which wraps os.CreateTemp
	// in an IOResult context for functional composition.
	//
	// This function takes a directory and pattern parameter and returns an IOResult
	// that produces a temporary file handle when executed.
	//
	// Parameters:
	//   - dir: directory where the temporary file should be created (empty string uses default temp dir)
	//   - pattern: filename pattern with optional '*' placeholder for random suffix
	//
	// Returns:
	//   IOResult[*os.File] that when executed creates and returns a temporary file handle
	//
	// Example:
	//   tempFile := CreateTemp("", "myapp-*.tmp")
	//   result := tempFile()
	//   file, err := E.UnwrapError(result)
	//   if err != nil {
	//       log.Fatal(err)
	//   }
	//   defer file.Close()
	CreateTemp = file.CreateTemp
)

Functions

This section is empty.

Types

type IOResult

type IOResult[T any] = ioresult.IOResult[T]

IOResult represents a synchronous computation that may fail, returning a Result type. It is an alias for ioresult.IOResult[T] which is equivalent to IO[Result[T]].

IOResult[T] is a function that when executed returns Result[T], which is Either[error, T]. This provides a functional approach to handling IO operations that may fail, with automatic resource management and composable error handling.

Example:

var readFile IOResult[[]byte] = func() Result[[]byte] {
    data, err := os.ReadFile("config.json")
    return result.TryCatchError(data, err)
}

// Execute the IO operation
result := readFile()
data, err := E.UnwrapError(result)

func Close

func Close[C io.Closer](c C) IOResult[struct{}]

Close closes an object

func Mkdir

func Mkdir(path string, perm os.FileMode) IOResult[string]

Mkdir create a directory, see os.Mkdir

func MkdirAll

func MkdirAll(path string, perm os.FileMode) IOResult[string]

MkdirAll create a sequence of directories, see os.MkdirAll

func ReadAll

func ReadAll[R io.ReadCloser](acquire IOResult[R]) IOResult[[]byte]

ReadAll uses a generator function to create a stream, reads it and closes it

func Remove

func Remove(name string) IOResult[string]

Remove removes a file by name

func WithTempFile

func WithTempFile[A any](f Kleisli[*os.File, A]) IOResult[A]

WithTempFile creates a temporary file, then invokes a callback to create a resource based on the file, then automatically closes and removes the temp file.

This function provides safe temporary file management by:

  1. Creating a temporary file with sensible defaults
  2. Passing the file handle to the provided callback function
  3. Ensuring the file is closed and removed, even if the callback fails

Type Parameters:

  • A: The type of result produced by the callback function

Parameters:

  • f: A Kleisli function that takes a *os.File and returns an IOResult[A]

Returns:

IOResult[A] that when executed creates a temp file, runs the callback,
and cleans up the file regardless of success or failure

Example - Writing and reading from a temporary file:

import (
    "io"
    "os"
    E "github.com/IBM/fp-go/v2/either"
    "github.com/IBM/fp-go/v2/ioresult"
    "github.com/IBM/fp-go/v2/ioresult/file"
)

// Write data to temp file and return the number of bytes written
writeToTemp := func(f *os.File) ioresult.IOResult[int] {
    return ioresult.TryCatchError(func() (int, error) {
        data := []byte("Hello, temporary world!")
        return f.Write(data)
    })
}

result := file.WithTempFile(writeToTemp)
bytesWritten, err := E.UnwrapError(result())
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Wrote %d bytes to temporary file\n", bytesWritten)

Example - Processing data through a temporary file:

processData := func(data []byte) ioresult.IOResult[string] {
    return file.WithTempFile(func(f *os.File) ioresult.IOResult[string] {
        return ioresult.TryCatchError(func() (string, error) {
            // Write data to temp file
            if _, err := f.Write(data); err != nil {
                return "", err
            }

            // Seek back to beginning
            if _, err := f.Seek(0, 0); err != nil {
                return "", err
            }

            // Read and process
            processed, err := io.ReadAll(f)
            if err != nil {
                return "", err
            }

            return strings.ToUpper(string(processed)), nil
        })
    })
}

result := processData([]byte("hello world"))
output, err := E.UnwrapError(result())
if err != nil {
    log.Fatal(err)
}
fmt.Println(output) // "HELLO WORLD"

The temporary file is guaranteed to be cleaned up even if the callback function panics or returns an error, providing safe resource management in a functional style.

type Kleisli

type Kleisli[A, B any] = ioresult.Kleisli[A, B]

Kleisli represents a function that takes a value of type A and returns an IOResult[B]. It is an alias for ioresult.Kleisli[A, B] which is equivalent to Reader[A, IOResult[B]].

Kleisli functions are the building blocks of monadic composition in the IOResult context. They allow for chaining operations that may fail while maintaining functional purity.

Example:

// A Kleisli function that reads from a file handle
var readAll Kleisli[*os.File, []byte] = func(f *os.File) IOResult[[]byte] {
    return TryCatchError(func() ([]byte, error) {
        return io.ReadAll(f)
    })
}

// Can be composed with other Kleisli functions
var processFile = F.Pipe1(
    file.Open("data.txt"),
    file.Read[[]byte, *os.File],
)(readAll)

func Read

func Read[R any, RD io.ReadCloser](acquire IOResult[RD]) Kleisli[Kleisli[RD, R], R]

Read uses a generator function to create a stream, reads data from it using a provided reader function, and ensures the stream is properly closed after reading.

This function provides safe resource management for reading operations by:

  1. Acquiring a ReadCloser resource using the provided acquire function
  2. Applying a reader function to extract data from the resource
  3. Ensuring the resource is closed, even if an error occurs during reading

Type Parameters:

  • R: The type of data to be read from the stream
  • RD: The type of the ReadCloser resource (must implement io.ReadCloser)

Parameters:

  • acquire: An IOResult that produces the ReadCloser resource

Returns:

A Kleisli function that takes a reader function (which transforms RD to R)
and returns an IOResult that produces the read result R or an error.

The key difference from ioeither.Read is that this returns IOResult[R] which is IO[Result[R]], representing a computation that returns a Result type (tuple of value and error) rather than an Either type.

Example - Reading first N bytes from a file:

import (
    "os"
    "io"
    F "github.com/IBM/fp-go/v2/function"
    R "github.com/IBM/fp-go/v2/result"
    "github.com/IBM/fp-go/v2/ioresult"
    "github.com/IBM/fp-go/v2/ioresult/file"
)

// Read first 10 bytes from a file
readFirst10 := func(f *os.File) ioresult.IOResult[[]byte] {
    return ioresult.TryCatch(func() ([]byte, error) {
        buf := make([]byte, 10)
        n, err := f.Read(buf)
        return buf[:n], err
    })
}

result := F.Pipe1(
    file.Open("data.txt"),
    file.Read[[]byte, *os.File],
)(readFirst10)

// Execute the IO operation to get the Result
res := result()
data, err := res()  // Result is a tuple function
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Read: %s\n", data)

Example - Using with Result combinators:

result := F.Pipe1(
    file.Open("config.json"),
    file.Read[[]byte, *os.File],
)(readFirst10)

// Chain operations using Result combinators
processed := F.Pipe2(
    result,
    ioresult.Map(func(data []byte) string {
        return string(data)
    }),
    ioresult.ChainFirst(func(s string) ioresult.IOResult[any] {
        return ioresult.Of[any](fmt.Printf("Read: %s\n", s))
    }),
)

res := processed()
str, err := res()
if err != nil {
    log.Fatal(err)
}

The Read function ensures that the file is closed even if the reading operation fails, providing safe and composable resource management in a functional style.

func Write

func Write[R any, W io.WriteCloser](acquire IOResult[W]) Kleisli[Kleisli[W, R], R]

Write uses a generator function to create a stream, writes data to it and closes it

func WriteFile

func WriteFile(dstName string, perm os.FileMode) Kleisli[[]byte, []byte]

WriteFile writes a data blob to a file

type Operator

type Operator[A, B any] = ioresult.Operator[A, B]

Operator represents a function that transforms one IOResult into another. It is an alias for ioresult.Operator[A, B] which is equivalent to Kleisli[IOResult[A], B].

Operators are used for transforming and composing IOResult values, providing a way to build complex data processing pipelines while maintaining error handling semantics.

Example:

// An operator that converts bytes to string
var bytesToString Operator[[]byte, string] = Map(func(data []byte) string {
    return string(data)
})

// An operator that validates JSON
var validateJSON Operator[string, map[string]interface{}] = ChainEitherK(
    func(s string) Result[map[string]interface{}] {
        var result map[string]interface{}
        err := json.Unmarshal([]byte(s), &result)
        return result.TryCatchError(result, err)
    },
)

// Compose operators in a pipeline
var processJSON = F.Pipe2(
    readFileOperation,
    bytesToString,
    validateJSON,
)

func WriteAll

func WriteAll[W io.WriteCloser](data []byte) Operator[W, []byte]

WriteAll uses a generator function to create a stream, writes data to it and closes it

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL